From e9700dd9ec89c399efec85f0c4bfa3b7bc9cb00b Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Thu, 10 Oct 2024 13:41:34 -0500 Subject: [PATCH] Migrate some doenetml worker tests to vitest (#240) * upgrade dependencies * set up test core to enable use of vitest in doenetml-worker * upgrade math-expressions * primitives removed from text state variables when from hidden composites * convert tests to vitest --- package-lock.json | 4434 +- package.json | 64 +- packages/docs-nextra/package.json | 4 +- packages/doenetml-worker/package.json | 2 +- packages/doenetml-worker/src/Core.js | 2 +- packages/doenetml-worker/src/Dependencies.js | 53 +- .../doenetml-worker/src/components/Answer.js | 12 + .../doenetml-worker/src/components/Caption.js | 2 +- .../doenetml-worker/src/components/Cell.js | 2 +- .../doenetml-worker/src/components/Choice.js | 2 +- .../src/components/Footnote.js | 2 +- .../doenetml-worker/src/components/Label.js | 3 + packages/doenetml-worker/src/components/P.js | 2 +- .../{Spreadsheet.js => Spreadsheet.ts} | 31 +- .../abstract/InlineRenderInlineChildren.js | 2 +- .../src/components/abstract/TextOrInline.js | 2 +- .../src/test/tagSpecific/answer.test.ts | 5693 +++ .../src/test/tagSpecific/boolean.test.ts} | 910 +- .../tagSpecific/conditionalcontent.test.ts | 1549 + .../src/test/tagSpecific/integer.test.ts | 133 + .../src/test/tagSpecific/lorem.test.ts | 242 + .../test/tagSpecific/matchespattern.test.ts} | 498 +- .../src/test/tagSpecific/math.test.ts | 9134 ++++ .../src/test/tagSpecific/mathinput.test.ts | 9225 ++++ .../test/tagSpecific/mathoperators.test.ts | 7782 ++++ .../src/test/tagSpecific/number.test.ts | 1960 + .../src/test/tagSpecific/p.test.ts | 45 + .../src/test/tagSpecific/polygon.test.ts | 6719 +++ .../src/test/tagSpecific/polyline.test.ts | 4588 ++ .../singlecharactercomponents.test.ts | 58 + .../src/test/tagSpecific/text.test.ts | 938 + .../src/test/tagSpecific/when.test.ts} | 160 +- .../doenetml-worker/src/test/utils/actions.ts | 134 + .../doenetml-worker/src/test/utils/math.ts | 6 + .../src/test/utils/test-core.ts | 110 + packages/doenetml-worker/src/utils/math.ts | 1 + packages/doenetml-worker/src/utils/text.js | 147 - packages/doenetml-worker/src/utils/text.ts | 170 + packages/doenetml/package.json | 7 +- .../cypress/e2e/tagSpecific/answer.cy.js | 35667 ++-------------- .../e2e/tagSpecific/conditionalcontent.cy.js | 3575 -- .../cypress/e2e/tagSpecific/integer.cy.js | 194 - .../cypress/e2e/tagSpecific/lorem.cy.js | 293 - .../cypress/e2e/tagSpecific/math.cy.js | 11613 +---- .../cypress/e2e/tagSpecific/mathinput.cy.js | 17327 +------- .../e2e/tagSpecific/mathoperators.cy.js | 14576 ------- .../cypress/e2e/tagSpecific/number.cy.js | 2439 -- .../cypress/e2e/tagSpecific/p.cy.js | 72 - .../cypress/e2e/tagSpecific/polygon.cy.js | 8993 +--- .../cypress/e2e/tagSpecific/polyline.cy.js | 5013 +-- .../singlecharactercomponents.cy.js | 78 - .../cypress/e2e/tagSpecific/text.cy.js | 635 - 52 files changed, 55008 insertions(+), 100295 deletions(-) rename packages/doenetml-worker/src/components/{Spreadsheet.js => Spreadsheet.ts} (98%) create mode 100644 packages/doenetml-worker/src/test/tagSpecific/answer.test.ts rename packages/{test-cypress/cypress/e2e/tagSpecific/boolean.cy.js => doenetml-worker/src/test/tagSpecific/boolean.test.ts} (62%) create mode 100644 packages/doenetml-worker/src/test/tagSpecific/conditionalcontent.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/integer.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/lorem.test.ts rename packages/{test-cypress/cypress/e2e/tagSpecific/matchespattern.cy.js => doenetml-worker/src/test/tagSpecific/matchespattern.test.ts} (59%) create mode 100644 packages/doenetml-worker/src/test/tagSpecific/math.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/mathinput.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/mathoperators.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/number.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/p.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/polygon.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/polyline.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/singlecharactercomponents.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/text.test.ts rename packages/{test-cypress/cypress/e2e/tagSpecific/when.cy.js => doenetml-worker/src/test/tagSpecific/when.test.ts} (56%) create mode 100644 packages/doenetml-worker/src/test/utils/actions.ts create mode 100644 packages/doenetml-worker/src/test/utils/math.ts create mode 100644 packages/doenetml-worker/src/test/utils/test-core.ts delete mode 100644 packages/doenetml-worker/src/utils/text.js create mode 100644 packages/doenetml-worker/src/utils/text.ts delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/conditionalcontent.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/integer.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/lorem.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/mathoperators.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/number.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/p.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js diff --git a/package-lock.json b/package-lock.json index 97747b0d5..f96fa96da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,57 +22,61 @@ "./packages/docs-nextra", "./packages/*" ], + "dependencies": { + "math-expressions": "^2.0.0-alpha68", + "react-router-dom": "^6.26.2" + }, "devDependencies": { - "@ariakit/react": "^0.4.7", + "@ariakit/react": "^0.4.11", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@esbuild-plugins/node-modules-polyfill": "^0.2.2", "@qualified/lsp-connection": "^0.3.0", "@qualified/vscode-jsonrpc-ww": "^0.3.0", - "@rollup/pluginutils": "^5.1.0", + "@rollup/pluginutils": "^5.1.2", "@types/esprima": "^4.0.6", - "@types/react": "^18.3.3", + "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", "@uiw/react-codemirror": "^4.22.2", "@vitejs/plugin-react": "^4.3.1", - "@vitest/web-worker": "^1.6.0", - "@vscode/test-web": "^0.0.54", - "autoprefixer": "^10.4.19", + "@vitest/web-worker": "^2.1.1", + "@vscode/test-web": "^0.0.60", + "autoprefixer": "^10.4.20", "chalk": "^5.3.0", "classnames": "^2.5.1", - "compress-json": "^3.0.5", - "cypress": "^12.13.0", - "cypress-parallel": "^0.13.0", + "compress-json": "^3.1.0", + "cypress": "^13.15.0", + "cypress-parallel": "^0.14.0", "cypress-plugin-tab": "^1.0.5", - "cypress-wait-until": "^1.7.2", - "eslint": "^8.57.0", - "eslint-plugin-react": "^7.34.2", + "cypress-wait-until": "^3.0.2", + "eslint": "^8.57.1", + "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.7", + "eslint-plugin-react-refresh": "^0.4.12", "esprima": "^4.0.1", - "glob": "^10.4.1", - "jsdom": "^24.1.0", - "katex": "^0.16.10", + "glob": "^10.4.5", + "jsdom": "^24.1.3", + "katex": "^0.16.11", "micromark": "^4.0.0", - "nextra": "^3.0.0-alpha.24", - "nextra-theme-docs": "^3.0.0-alpha.24", - "node-stdlib-browser": "^1.2.0", - "postcss": "^8.4.38", - "prettier": "^3.3.2", + "nextra": "^3.0.1", + "nextra-theme-docs": "^3.0.1", + "node-stdlib-browser": "^1.2.1", + "postcss": "^8.4.47", + "prettier": "^3.3.3", "rollup-plugin-polyfill-node": "^0.13.0", "rollup-plugin-visualizer": "^5.12.0", - "tailwindcss": "^3.4.4", + "tailwindcss": "^3.4.13", "ts-morph": "^22.0.0", - "typescript": "^5.4.5", - "vite": "^5.3.0", - "vite-node": "^1.6.0", + "typescript": "^5.6.2", + "vite": "^5.4.8", + "vite-node": "^2.1.1", "vite-plugin-compile-time": "^0.2.1", - "vite-plugin-dts": "^3.9.1", - "vite-plugin-static-copy": "^1.0.5", - "vitest": "^1.6.0", - "vscode-jsonrpc": "8.2.0", + "vite-plugin-dts": "^4.2.2", + "vite-plugin-static-copy": "^1.0.6", + "vitest": "^2.1.1", + "vscode-jsonrpc": "8.2.1", "vscode-languageserver": "^9.0.1", "vscode-languageserver-protocol": "^3.17.5", - "wireit": "^0.14.4" + "wireit": "^0.14.9" } }, "node_modules/@alloc/quick-lru": { @@ -99,19 +103,43 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/install-pkg": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-0.4.1.tgz", + "integrity": "sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^0.2.0", + "tinyexec": "^0.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@ariakit/core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.7.tgz", - "integrity": "sha512-GUy/3ZY4kW1KdYHtMZRrRlj5FYbZTAyHlimxHI7Zs0xsC+kAzIf8lopnf67Y9IYLgEMr37KosIV7kwpkJpNs5Q==", - "dev": true + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/@ariakit/core/-/core-0.4.10.tgz", + "integrity": "sha512-mX3EabQbfVh5uTjsTJ3+gjj7KGdTNhIN0qZHJd5Z2iPUnKl9NBy23Lgu6PEskpVsKAZ3proirjguD7U9fKMs/A==", + "dev": true, + "license": "MIT" }, "node_modules/@ariakit/react": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.7.tgz", - "integrity": "sha512-uUruuCo1M0Nj2oq1nTwDfUlVTLuoI9xeHP75EkuXX46lg5hzE5vVWbSMO1D6MCy7UwrUx2Ts4IqxdKr97suTwQ==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@ariakit/react/-/react-0.4.11.tgz", + "integrity": "sha512-nLpPrmNcspqNhk4o+epsgeZfP1+Fkh4uIzNe5yrFkXolRkqHGKAxl4Hi82e0yxIBUbYbZIEwsZQQVceF1L6xrw==", "dev": true, + "license": "MIT", "dependencies": { - "@ariakit/react-core": "0.4.7" + "@ariakit/react-core": "0.4.11" }, "funding": { "type": "opencollective", @@ -123,12 +151,13 @@ } }, "node_modules/@ariakit/react-core": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.7.tgz", - "integrity": "sha512-OogUyQ20cxkRNRuqLI05JbmpR4Lr5HwhUIqnb/sipzt6bkg/3wCXEnUAjfxg3nPjLTMjJ8+ODWmPC9JMJTW/yg==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@ariakit/react-core/-/react-core-0.4.11.tgz", + "integrity": "sha512-i6KedWhjZkNC7tMEKO0eNjjq2HRPiHyGaBS2x2VaWwzBepoYtjyvxRXyqLJ3gaiNdlwckN1TZsRDfD+viy13IQ==", "dev": true, + "license": "MIT", "dependencies": { - "@ariakit/core": "0.4.7", + "@ariakit/core": "0.4.10", "@floating-ui/dom": "^1.0.0", "use-sync-external-store": "^1.2.0" }, @@ -138,9 +167,10 @@ } }, "node_modules/@babel/cli": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.24.8.tgz", - "integrity": "sha512-isdp+G6DpRyKc+3Gqxy2rjzgF7Zj9K0mzLNnxz+E/fgeag8qT3vVulX4gY9dGO1q0y+0lUv6V3a+uhUzMzrwXg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.25.7.tgz", + "integrity": "sha512-vQw4QjrqjLSuL0Tt3gfVXbxEHOfsCcHN8tKyTclpSMYLq3Bp0BTzWYZfMKBs3PQ+to8q3BnumBIAsMdOqDJ6nw==", + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "commander": "^6.2.0", @@ -159,7 +189,7 @@ }, "optionalDependencies": { "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", - "chokidar": "^3.4.0" + "chokidar": "^3.6.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -170,6 +200,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -189,6 +220,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "license": "MIT", "engines": { "node": ">=6" } @@ -492,9 +524,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.6" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -551,6 +587,7 @@ "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", "deprecated": "🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.", + "license": "MIT", "dependencies": { "core-js": "^2.6.5", "regenerator-runtime": "^0.13.4" @@ -561,17 +598,20 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true + "hasInstallScript": true, + "license": "MIT" }, "node_modules/@babel/polyfill/node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" }, "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -613,9 +653,10 @@ } }, "node_modules/@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", @@ -626,9 +667,10 @@ } }, "node_modules/@braintree/sanitize-url": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", - "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==" + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.0.tgz", + "integrity": "sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==", + "license": "MIT" }, "node_modules/@chakra-ui/accordion": { "version": "2.3.1", @@ -1807,6 +1849,45 @@ "react": ">=18" } }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0" + }, "node_modules/@codemirror/autocomplete": { "version": "6.17.0", "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.17.0.tgz", @@ -1918,10 +1999,11 @@ } }, "node_modules/@cypress/request": { - "version": "2.88.12", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.12.tgz", - "integrity": "sha512-tOn+0mDZxASFM+cuAP9szGUGPI1HwWVSvdzm7V4cCsPdFTx6qMj29CwaQmRAMIEhORIUBFBsYROYJcveK4uOjA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.5.tgz", + "integrity": "sha512-v+XHd9XmWbufxF1/bTaVm2yhbxY+TB4YtWRqF2zaXBlDNMkls34KiATz0AVDLavL3iB6bQk9/7n3oY1EoLSWGA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -1929,14 +2011,14 @@ "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", + "form-data": "~4.0.0", + "http-signature": "~1.4.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "~6.10.3", + "qs": "6.13.0", "safe-buffer": "^5.1.2", "tough-cookie": "^4.1.3", "tunnel-agent": "^0.6.0", @@ -2664,6 +2746,7 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -2687,6 +2770,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -2702,6 +2786,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -2710,10 +2795,11 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -2722,7 +2808,6 @@ "version": "1.6.4", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.4.tgz", "integrity": "sha512-a4IowK4QkXl4SCWTGUR0INAfEOX3wtsYw3rKK5InQEHMGObkR8Xk44qYQD9P4r6HHw0iIfK6GUKECmY8sTkqRA==", - "dev": true, "dependencies": { "@floating-ui/utils": "^0.2.4" } @@ -2731,17 +2816,50 @@ "version": "1.6.7", "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.7.tgz", "integrity": "sha512-wmVfPG5o2xnKDU4jx/m4w5qva9FWHcnZ8BvzEe90D/RpwsJaTAVYPEPdQ8sbr/N8zZTAHlZUTQdqg8ZUbzHmng==", - "dev": true, "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.4" } }, + "node_modules/@floating-ui/react": { + "version": "0.26.24", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.24.tgz", + "integrity": "sha512-2ly0pCkZIGEQUq5H8bBK0XJmc1xIK/RM3tvVzY3GBER7IOD1UgmC2Y2tjj4AuS+TC+vTE1KJv2053290jua0Sw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react/node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "license": "MIT" + }, "node_modules/@floating-ui/utils": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz", - "integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==", - "dev": true + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", + "license": "MIT" }, "node_modules/@fortawesome/fontawesome-common-types": { "version": "6.5.2", @@ -2809,29 +2927,33 @@ } }, "node_modules/@headlessui/react": { - "version": "1.7.19", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz", - "integrity": "sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.1.8.tgz", + "integrity": "sha512-uajqVkAcVG/wHwG9Fh5PFMcFpf2VxM4vNRNKxRjuK009kePVur8LkuuygHfIE+2uZ7z7GnlTtYsyUe6glPpTLg==", + "license": "MIT", "dependencies": { - "@tanstack/react-virtual": "^3.0.0-beta.60", - "client-only": "^0.0.1" + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@tanstack/react-virtual": "^3.8.1" }, "engines": { "node": ">=10" }, "peerDependencies": { - "react": "^16 || ^17 || ^18", - "react-dom": "^16 || ^17 || ^18" + "react": "^18", + "react-dom": "^18" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -2857,7 +2979,29 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "deprecated": "Use @eslint/object-schema instead", - "dev": true + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.1.33.tgz", + "integrity": "sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^0.4.0", + "@antfu/utils": "^0.7.10", + "@iconify/types": "^2.0.0", + "debug": "^4.3.6", + "kolorist": "^1.8.0", + "local-pkg": "^0.5.0", + "mlly": "^1.7.1" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -2926,18 +3070,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -2994,19 +3126,18 @@ } }, "node_modules/@koa/router": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.1.tgz", - "integrity": "sha512-ribfPYfHb+Uw3b27Eiw6NPqjhIhTpVFzEWLwyc/1Xp+DCdwRRyIlAUODX+9bPARF6aQtUu1+/PHzdNvRzcs/+Q==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/@koa/router/-/router-13.1.0.tgz", + "integrity": "sha512-mNVu1nvkpSd8Q8gMebGbCkDWJ51ODetrFvLKYusej+V0ByD4btqHYnPIzTBLXnQMVUlm/oxVwqmWBY3zQfZilw==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.3.4", "http-errors": "^2.0.0", "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.2.1" + "path-to-regexp": "^6.3.0" }, "engines": { - "node": ">= 12" + "node": ">= 18" } }, "node_modules/@lezer/common": { @@ -3110,19 +3241,29 @@ "react": ">=16" } }, + "node_modules/@mermaid-js/parser": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.3.0.tgz", + "integrity": "sha512-HsvL6zgE5sUPGgkIDlmAWR1HTNHz2Iy11BAWPTa4Jjabkpguy4Ze2gzfLrg6pdRuBvFwgUYyxiaNqZwrEEXepA==", + "license": "MIT", + "dependencies": { + "langium": "3.0.0" + } + }, "node_modules/@microsoft/api-extractor": { - "version": "7.43.0", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.43.0.tgz", - "integrity": "sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==", - "dev": true, - "dependencies": { - "@microsoft/api-extractor-model": "7.28.13", - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "4.0.2", - "@rushstack/rig-package": "0.5.2", - "@rushstack/terminal": "0.10.0", - "@rushstack/ts-command-line": "4.19.1", + "version": "7.47.7", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.47.7.tgz", + "integrity": "sha512-fNiD3G55ZJGhPOBPMKD/enozj8yxJSYyVJWxRWdcUtw842rvthDHJgUWq9gXQTensFlMHv2wGuCjjivPv53j0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@microsoft/api-extractor-model": "7.29.6", + "@microsoft/tsdoc": "~0.15.0", + "@microsoft/tsdoc-config": "~0.17.0", + "@rushstack/node-core-library": "5.7.0", + "@rushstack/rig-package": "0.5.3", + "@rushstack/terminal": "0.14.0", + "@rushstack/ts-command-line": "4.22.6", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", @@ -3135,14 +3276,15 @@ } }, "node_modules/@microsoft/api-extractor-model": { - "version": "7.28.13", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.28.13.tgz", - "integrity": "sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==", + "version": "7.29.6", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.29.6.tgz", + "integrity": "sha512-gC0KGtrZvxzf/Rt9oMYD2dHvtN/1KPEYsrQPyMKhLHnlVuO/f4AFN3E4toqZzD2pt4LhkKoYmL2H9tX3yCOyRw==", "dev": true, + "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "@microsoft/tsdoc-config": "~0.16.1", - "@rushstack/node-core-library": "4.0.2" + "@microsoft/tsdoc": "~0.15.0", + "@microsoft/tsdoc-config": "~0.17.0", + "@rushstack/node-core-library": "5.7.0" } }, "node_modules/@microsoft/api-extractor/node_modules/lru-cache": { @@ -3150,6 +3292,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -3162,6 +3305,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3174,6 +3318,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -3191,6 +3336,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3206,6 +3352,7 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -3215,6 +3362,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3227,7 +3375,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@microsoft/fast-element": { "version": "1.13.0", @@ -3276,31 +3425,62 @@ } }, "node_modules/@microsoft/tsdoc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", - "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", - "dev": true + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==", + "dev": true, + "license": "MIT" }, "node_modules/@microsoft/tsdoc-config": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", - "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.17.0.tgz", + "integrity": "sha512-v/EYRXnCAIHxOHW+Plb6OWuUoMotxTN0GLatnpOb1xq0KuTNw/WI3pamJx/UbsoJP5k9MCw1QxvvhPcF9pH3Zg==", "dev": true, + "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "0.14.2", - "ajv": "~6.12.6", + "@microsoft/tsdoc": "0.15.0", + "ajv": "~8.12.0", "jju": "~1.4.0", - "resolve": "~1.19.0" + "resolve": "~1.22.2" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3310,6 +3490,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "license": "MIT", "dependencies": { "call-me-maybe": "^1.0.1", "glob-to-regexp": "^0.3.0" @@ -3658,6 +3839,7 @@ "version": "2.1.8-no-fsevents.3", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", + "license": "MIT", "optional": true }, "node_modules/@nodelib/fs.scandir": { @@ -3747,13 +3929,14 @@ } }, "node_modules/@playwright/browser-chromium": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/@playwright/browser-chromium/-/browser-chromium-1.45.2.tgz", - "integrity": "sha512-oYWP32mCpEtPCE26uY+e82oF/oHa8y6Hx9EPN7ljrHyo6hb+/NDXp6OoJEZ/bwnGHEMKxfeD4yre0iXxBOLTxA==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/@playwright/browser-chromium/-/browser-chromium-1.47.2.tgz", + "integrity": "sha512-tsk9bLcGzIu4k4xI2ixlwDrdJhMqCalUCsSj7TRI8VuvK7cLiJIa5SR0dprKbX+wkku/JMR4EN6g9DMHvfna+Q==", "dev": true, "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.45.2" + "playwright-core": "1.47.2" }, "engines": { "node": ">=18" @@ -3786,10 +3969,94 @@ "vscode-jsonrpc": "^8.0.1" } }, + "node_modules/@react-aria/focus": { + "version": "3.18.2", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.18.2.tgz", + "integrity": "sha512-Jc/IY+StjA3uqN73o6txKQ527RFU7gnG5crEl5Xy3V+gbYp2O5L3ezAo/E0Ipi2cyMbG6T5Iit1IDs7hcGu8aw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.22.2", + "@react-aria/utils": "^3.25.2", + "@react-types/shared": "^3.24.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.22.2", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.22.2.tgz", + "integrity": "sha512-xE/77fRVSlqHp2sfkrMeNLrqf2amF/RyuAS6T5oDJemRSgYM3UoxTbWjucPhfnoW7r32pFPHHgz4lbdX8xqD/g==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.5", + "@react-aria/utils": "^3.25.2", + "@react-types/shared": "^3.24.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.5.tgz", + "integrity": "sha512-xEwGKoysu+oXulibNUSkXf8itW0npHHTa6c4AyYeZIJyRoegeteYuFpZUBPtIDE8RfHdNsSmE1ssOkxRnwbkuQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.25.2.tgz", + "integrity": "sha512-GdIvG8GBJJZygB4L2QJP1Gabyn2mjFsha73I2wSe+o4DYeGWoJiMZRM06PyTIxLH4S7Sn7eVDtsSBfkc2VY/NA==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.5", + "@react-stately/utils": "^3.10.3", + "@react-types/shared": "^3.24.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.3.tgz", + "integrity": "sha512-moClv7MlVSHpbYtQIkm0Cx+on8Pgt1XqtPx6fy9rQFb2DNc9u1G3AUVnqA17buOkH1vLxAtX4MedlxMWyRCYYA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-types/shared": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.24.1.tgz", + "integrity": "sha512-AUQeGYEm/zDTN6zLzdXolDxz3Jk5dDL7f506F07U8tBwxNNI3WRdhU84G0/AaFikOZzDXhOZDr3MhQMzyE7Ydw==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@remix-run/router": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", - "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz", + "integrity": "sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==", + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -3826,10 +4093,11 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", + "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", @@ -3848,225 +4116,244 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", - "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.5.tgz", + "integrity": "sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", - "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.5.tgz", + "integrity": "sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", - "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.5.tgz", + "integrity": "sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", - "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.5.tgz", + "integrity": "sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", - "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.5.tgz", + "integrity": "sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", - "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.5.tgz", + "integrity": "sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", - "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.5.tgz", + "integrity": "sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", - "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.5.tgz", + "integrity": "sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", - "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.5.tgz", + "integrity": "sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", - "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.5.tgz", + "integrity": "sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", - "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.5.tgz", + "integrity": "sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", - "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.5.tgz", + "integrity": "sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", - "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.5.tgz", + "integrity": "sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", - "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.5.tgz", + "integrity": "sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", - "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.5.tgz", + "integrity": "sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", - "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.5.tgz", + "integrity": "sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rushstack/node-core-library": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-4.0.2.tgz", - "integrity": "sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.7.0.tgz", + "integrity": "sha512-Ff9Cz/YlWu9ce4dmqNBZpA45AEya04XaBFIjV7xTVeEf+y/kTjEasmozqFELXlNG4ROdevss75JrrZ5WgufDkQ==", "dev": true, + "license": "MIT", "dependencies": { + "ajv": "~8.13.0", + "ajv-draft-04": "~1.0.0", + "ajv-formats": "~3.0.1", "fs-extra": "~7.0.1", "import-lazy": "~4.0.0", "jju": "~1.4.0", "resolve": "~1.22.1", - "semver": "~7.5.4", - "z-schema": "~5.0.2" + "semver": "~7.5.4" }, "peerDependencies": { "@types/node": "*" @@ -4077,11 +4364,44 @@ } } }, + "node_modules/@rushstack/node-core-library/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/@rushstack/node-core-library/node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -4091,11 +4411,19 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/@rushstack/node-core-library/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/@rushstack/node-core-library/node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, + "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -4105,6 +4433,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -4117,6 +4446,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -4134,6 +4464,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -4149,6 +4480,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -4157,13 +4489,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@rushstack/rig-package": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.2.tgz", - "integrity": "sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.3.tgz", + "integrity": "sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==", "dev": true, + "license": "MIT", "dependencies": { "resolve": "~1.22.1", "strip-json-comments": "~3.1.1" @@ -4174,6 +4508,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -4187,12 +4522,13 @@ } }, "node_modules/@rushstack/terminal": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.10.0.tgz", - "integrity": "sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.0.tgz", + "integrity": "sha512-juTKMAMpTIJKudeFkG5slD8Z/LHwNwGZLtU441l/u82XdTBfsP+LbGKJLCNwP5se+DMCT55GB8x9p6+C4UL7jw==", "dev": true, + "license": "MIT", "dependencies": { - "@rushstack/node-core-library": "4.0.2", + "@rushstack/node-core-library": "5.7.0", "supports-color": "~8.1.1" }, "peerDependencies": { @@ -4205,12 +4541,13 @@ } }, "node_modules/@rushstack/ts-command-line": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.19.1.tgz", - "integrity": "sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==", + "version": "4.22.6", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.22.6.tgz", + "integrity": "sha512-QSRqHT/IfoC5nk9zn6+fgyqOPXHME0BfchII9EUPR19pocsNp/xSbeBCbD3PIR2Lg+Q5qk7OFqk1VhWPMdKHJg==", "dev": true, + "license": "MIT", "dependencies": { - "@rushstack/terminal": "0.10.0", + "@rushstack/terminal": "0.14.0", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" @@ -4221,6 +4558,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } @@ -4233,6 +4571,27 @@ "@types/hast": "^3.0.4" } }, + "node_modules/@shikijs/engine-javascript": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.20.0.tgz", + "integrity": "sha512-ZUMo758uduM0Tfgzi/kd+0IKMbNdumCxxWjY36uf1DIs2Qyg9HIq3vA1Wfa/vc6HE7tHWFpANRi3mv7UzJ68MQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.20.0", + "@shikijs/vscode-textmate": "^9.2.2", + "oniguruma-to-js": "0.4.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.20.0.tgz", + "integrity": "sha512-MQ40WkVTZk7by33ces4PGK6XNFSo6PYvKTSAr2kTWdRNhFmOcnaX+1XzvFwB26eySXR7U74t91czZ1qJkEgxTA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "1.20.0", + "@shikijs/vscode-textmate": "^9.2.2" + } + }, "node_modules/@shikijs/twoslash": { "version": "1.10.3", "resolved": "https://registry.npmjs.org/@shikijs/twoslash/-/twoslash-1.10.3.tgz", @@ -4242,34 +4601,43 @@ "twoslash": "^0.2.9" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "node_modules/@shikijs/types": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.20.0.tgz", + "integrity": "sha512-y+EaDvU2K6/GaXOKXxJaGnr1XtmZMF7MfS0pSEDdxEq66gCtKsLwQvVwoQFdp7R7dLlNAro3ijEE19sMZ0pzqg==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^9.2.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-9.2.2.tgz", + "integrity": "sha512-TMp15K+GGYrWlZM8+Lnj9EaHEFmOen0WJBrfa17hF7taDOYthuPPV0GWzfd/9iMij0akS/8Yw2ikquH7uVi/fg==", + "license": "MIT" }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "peer": true + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" }, "node_modules/@swc/helpers": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", - "peer": true, "dependencies": { "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, "node_modules/@tanstack/react-virtual": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.8.3.tgz", - "integrity": "sha512-9ICwbDUUzN99CJIGc373i8NLoj6zFTKI2Hlcmo0+lCSAhPQ5mxq4dGOMKmLYoEFyHcGQ64Bd6ZVbnPpM6lNK5w==", + "version": "3.10.8", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.10.8.tgz", + "integrity": "sha512-VbzbVGSsZlQktyLrP5nxE+vE1ZR+U0NFAWPbJLoG2+DKPwd2D7dVICTVIIaYlJqX1ZCEnYDbaOpmMwbsyhBoIA==", + "license": "MIT", "dependencies": { - "@tanstack/virtual-core": "3.8.3" + "@tanstack/virtual-core": "3.10.8" }, "funding": { "type": "github", @@ -4281,20 +4649,22 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.8.3.tgz", - "integrity": "sha512-vd2A2TnM5lbnWZnHi9B+L2gPtkSeOtJOAw358JqokIH1+v2J7vUAzFVPwB/wrye12RFOurffXu33plm4uQ+JBQ==", + "version": "3.10.8", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.10.8.tgz", + "integrity": "sha512-PBu00mtt95jbKFi6Llk9aik8bnR3tR/oQP1o3TSi+iG//+Q2RTIzCEgKkHG8BB86kxMNW6O8wku+Lmi+QFR6jA==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@theguild/remark-mermaid": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@theguild/remark-mermaid/-/remark-mermaid-0.0.5.tgz", - "integrity": "sha512-e+ZIyJkEv9jabI4m7q29wZtZv+2iwPGsXJ2d46Zi7e+QcFudiyuqhLhHG/3gX3ZEB+hxTch+fpItyMS8jwbIcw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@theguild/remark-mermaid/-/remark-mermaid-0.1.3.tgz", + "integrity": "sha512-2FjVlaaKXK7Zj7UJAgOVTyaahn/3/EAfqYhyXg0BfDBVUl+lXcoIWRaxzqfnDr2rv8ax6GsC5mNh6hAaT86PDw==", + "license": "MIT", "dependencies": { - "mermaid": "^10.2.2", + "mermaid": "^11.0.0", "unist-util-visit": "^5.0.0" }, "peerDependencies": { @@ -4302,11 +4672,12 @@ } }, "node_modules/@theguild/remark-npm2yarn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@theguild/remark-npm2yarn/-/remark-npm2yarn-0.3.0.tgz", - "integrity": "sha512-Fofw+9airYgjBd9G6PiHHCrptjyUybQ50JH9/5o9LCH54kggJ7stpCofzHjICB8L7VQbQ1Gwu23P/3CMVY1R4Q==", - "dependencies": { - "npm-to-yarn": "^2.1.0", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@theguild/remark-npm2yarn/-/remark-npm2yarn-0.3.2.tgz", + "integrity": "sha512-H9T/GOuS/+4H7AY1cfD5DJIIIcGIIw1zMCB8OeTgXk7azJULsnuOurZ/CR54rvuTD+Krx0MVQccaUCvCWfP+vw==", + "license": "MIT", + "dependencies": { + "npm-to-yarn": "^3.0.0", "unist-util-visit": "^5.0.0" } }, @@ -4358,7 +4729,8 @@ "version": "1.0.38", "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -4401,24 +4773,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/d3-scale": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", - "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-scale-chromatic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", - "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==" - }, - "node_modules/@types/d3-time": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", - "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -4437,9 +4791,10 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "license": "MIT" }, "node_modules/@types/estree-jsx": { "version": "1.0.5", @@ -4453,6 +4808,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "license": "MIT", "dependencies": { "@types/minimatch": "*", "@types/node": "*" @@ -4500,7 +4856,8 @@ "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "license": "MIT" }, "node_modules/@types/ms": { "version": "0.7.34", @@ -4508,18 +4865,14 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/nlcst": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-1.0.4.tgz", - "integrity": "sha512-ABoYdNQ/kBSsLvZAekMhIPMQ3YUZvavStpKYs7BjLLuKVmIMA0LUgZ7b54zzuWJRbHF80v1cNf4r90Vd6eMQDg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "license": "MIT", "dependencies": { - "@types/unist": "^2" + "@types/unist": "*" } }, - "node_modules/@types/nlcst/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -4531,7 +4884,8 @@ "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "license": "MIT" }, "node_modules/@types/parse-json": { "version": "4.0.2", @@ -4553,9 +4907,10 @@ "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "version": "18.3.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.10.tgz", + "integrity": "sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==", + "license": "MIT", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -4709,148 +5064,192 @@ } }, "node_modules/@vitest/expect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", - "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", + "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "chai": "^4.3.10" + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/runner": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", - "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "node_modules/@vitest/mocker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", + "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/utils": "1.6.0", - "p-limit": "^5.0.0", - "pathe": "^1.1.1" + "@vitest/spy": "^2.1.0-beta.1", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" }, "funding": { "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.1", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/mocker/node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", + "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", "dev": true, + "license": "MIT", "dependencies": { - "yocto-queue": "^1.0.0" + "tinyrainbow": "^1.2.0" }, - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", + "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.1", + "pathe": "^1.1.2" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", - "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", + "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", "dev": true, + "license": "MIT", "dependencies": { - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "pretty-format": "^29.7.0" + "@vitest/pretty-format": "2.1.1", + "magic-string": "^0.30.11", + "pathe": "^1.1.2" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot/node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/@vitest/spy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", - "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", + "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", "dev": true, + "license": "MIT", "dependencies": { - "tinyspy": "^2.2.0" + "tinyspy": "^3.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", + "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", "dev": true, + "license": "MIT", "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" + "@vitest/pretty-format": "2.1.1", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/utils/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/@vitest/web-worker": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/web-worker/-/web-worker-1.6.0.tgz", - "integrity": "sha512-VVKzjk6PVKfaXfhRwTxXaQ0NCp2BoUPhiR2OYd3InZb60jbZVmKquvngFXgvgOf1aDT8ztloMi8yu3wj9eRcuQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@vitest/web-worker/-/web-worker-2.1.1.tgz", + "integrity": "sha512-9APtqy5bmpD9l7q6NZ3iN3w3cUd7IBHH5+8VvrwedqItomz7JLeb5Mj0E1Pfh9Jo3thI87ClipY+aL2HROmzfA==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "^4.3.4" + "debug": "^4.3.6" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "^1.0.0" + "vitest": "2.1.1" } }, "node_modules/@volar/language-core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", - "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.5.tgz", + "integrity": "sha512-F4tA0DCO5Q1F5mScHmca0umsi2ufKULAnMOVBfMsZdT4myhVl4WdKRwCaKcfOkIEuyrAVvtq1ESBdZ+rSyLVww==", "dev": true, + "license": "MIT", "dependencies": { - "@volar/source-map": "1.11.1" + "@volar/source-map": "2.4.5" } }, "node_modules/@volar/source-map": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", - "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.5.tgz", + "integrity": "sha512-varwD7RaKE2J/Z+Zu6j3mNNJbNT394qIxXwdvz/4ao/vxOfyClZpSDtLKkwWmecinkOVos5+PWkWraelfMLfpw==", "dev": true, - "dependencies": { - "muggle-string": "^0.3.1" - } + "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", - "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.5.tgz", + "integrity": "sha512-mcT1mHvLljAEtHviVcBuOyAwwMKz1ibXTi5uYtP/pf4XxoAzpdkQ+Br2IC0NPCvLCbjPZmbf3I0udndkfB1CDg==", "dev": true, + "license": "MIT", "dependencies": { - "@volar/language-core": "1.11.1", - "path-browserify": "^1.0.1" + "@volar/language-core": "2.4.5", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" } }, "node_modules/@vscode/test-electron": { @@ -4882,33 +5281,128 @@ } }, "node_modules/@vscode/test-web": { - "version": "0.0.54", - "resolved": "https://registry.npmjs.org/@vscode/test-web/-/test-web-0.0.54.tgz", - "integrity": "sha512-LDdFFEzmnKQ96QmuRxK9kRhddQmwqyI/VOb6YhyPqOsbKBIM7uzTqpckoueOu9EEnvPSNQNoxqb426AakI8e5w==", + "version": "0.0.60", + "resolved": "https://registry.npmjs.org/@vscode/test-web/-/test-web-0.0.60.tgz", + "integrity": "sha512-U3Eif3GZEfmtFJFTRl5IZUxlqDocslvpHCoW4uz407F9YINc2ujJPB0QG+9ZtjjowZDzFJlg60J44RqmnlA0cg==", "dev": true, + "license": "MIT", "dependencies": { "@koa/cors": "^5.0.0", - "@koa/router": "^12.0.1", - "@playwright/browser-chromium": "^1.43.1", + "@koa/router": "^13.0.0", + "@playwright/browser-chromium": "^1.47.0", + "glob": "^11.0.0", "gunzip-maybe": "^1.4.2", "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.4", + "https-proxy-agent": "^7.0.5", "koa": "^2.15.3", "koa-morgan": "^1.0.1", "koa-mount": "^4.0.0", "koa-static": "^5.0.0", "minimist": "^1.2.8", - "playwright": "^1.43.1", - "tar-fs": "^3.0.5", + "playwright": "^1.47.0", + "tar-fs": "^3.0.6", "vscode-uri": "^3.0.8" }, "bin": { - "vscode-test-web": "out/index.js" + "vscode-test-web": "out/server/index.js" }, "engines": { "node": ">=16" } }, + "node_modules/@vscode/test-web/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@vscode/test-web/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-web/node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-web/node_modules/lru-cache": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@vscode/test-web/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/test-web/node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@vscode/webview-ui-toolkit": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.4.0.tgz", @@ -4925,43 +5419,56 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.4.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.31.tgz", - "integrity": "sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==", + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.10.tgz", + "integrity": "sha512-iXWlk+Cg/ag7gLvY0SfVucU8Kh2CjysYZjhhP70w9qI4MvSox4frrP+vDGvtQuzIcgD8+sxM6lZvCtdxGunTAA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.24.7", - "@vue/shared": "3.4.31", + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.10", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.31.tgz", - "integrity": "sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==", + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.10.tgz", + "integrity": "sha512-DyxHC6qPcktwYGKOIy3XqnHRrrXyWR2u91AjP+nLkADko380srsC2DC3s7Y1Rk6YfOlxOlvEQKa9XXmLI+W4ZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.10", + "@vue/shared": "3.5.10" + } + }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", "dev": true, + "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.4.31", - "@vue/shared": "3.4.31" + "de-indent": "^1.0.2", + "he": "^1.2.0" } }, "node_modules/@vue/language-core": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", - "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.1.6.tgz", + "integrity": "sha512-MW569cSky9R/ooKMh6xa2g1D0AtRKbL56k83dzus/bx//RDJk24RHWkMzbAlXjMdDNyxAaagKPRquBIxkxlCkg==", "dev": true, + "license": "MIT", "dependencies": { - "@volar/language-core": "~1.11.1", - "@volar/source-map": "~1.11.1", - "@vue/compiler-dom": "^3.3.0", - "@vue/shared": "^3.3.0", + "@volar/language-core": "~2.4.1", + "@vue/compiler-dom": "^3.4.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.4.0", "computeds": "^0.0.1", "minimatch": "^9.0.3", - "muggle-string": "^0.3.1", - "path-browserify": "^1.0.1", - "vue-template-compiler": "^2.7.14" + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" @@ -4977,6 +5484,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -4986,6 +5494,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -4997,10 +5506,11 @@ } }, "node_modules/@vue/shared": { - "version": "3.4.31", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.31.tgz", - "integrity": "sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==", - "dev": true + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.10.tgz", + "integrity": "sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ==", + "dev": true, + "license": "MIT" }, "node_modules/@zag-js/dom-query": { "version": "0.16.0", @@ -5052,18 +5562,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", - "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -5094,6 +5592,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5105,6 +5604,48 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/ally.js": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/ally.js/-/ally.js-1.4.1.tgz", @@ -5228,6 +5769,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5236,6 +5778,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5244,6 +5787,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5288,6 +5832,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -5297,6 +5842,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "license": "MIT", "dependencies": { "array-uniq": "^1.0.1" }, @@ -5308,6 +5854,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5316,6 +5863,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5376,18 +5924,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, "node_modules/array.prototype.tosorted": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", @@ -5431,6 +5967,7 @@ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, + "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" } @@ -5470,23 +6007,26 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } }, "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">=12" } }, "node_modules/assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5532,6 +6072,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "license": "(MIT OR Apache-2.0)", "bin": { "atob": "bin/atob.js" }, @@ -5540,9 +6081,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", - "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", "dev": true, "funding": [ { @@ -5558,12 +6099,13 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "browserslist": "^4.23.0", - "caniuse-lite": "^1.0.30001599", + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "postcss-value-parser": "^4.2.0" }, "bin": { @@ -5596,15 +6138,17 @@ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "*" } }, "node_modules/aws4": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.0.tgz", - "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==", - "dev": true + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true, + "license": "MIT" }, "node_modules/axios": { "version": "0.27.2", @@ -5615,19 +6159,6 @@ "form-data": "^4.0.0" } }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", @@ -5685,6 +6216,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-upgrade/-/babel-upgrade-1.0.1.tgz", "integrity": "sha512-1+aRupa4DvXXxVYxC2ejWnul/7Pi1T3hYUmnq4gxgkV/NGJMWpKdtipv7fb0cdS3ifdvryIboAi1fLHLZjHvbg==", + "license": "MIT", "dependencies": { "@babel/polyfill": "^7.0.0", "commander": "^2.18.0", @@ -5711,12 +6243,14 @@ "node_modules/babel-upgrade/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" }, "node_modules/babel-upgrade/node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "license": "MIT", "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -5732,6 +6266,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -5740,6 +6275,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", "engines": { "node": ">=4" } @@ -5748,6 +6284,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", "engines": { "node": ">=6" } @@ -5756,6 +6293,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -5764,6 +6302,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", "dependencies": { "shebang-regex": "^1.0.0" }, @@ -5775,6 +6314,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5783,6 +6323,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -5854,6 +6395,7 @@ "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "license": "MIT", "dependencies": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -5871,6 +6413,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "license": "MIT", "dependencies": { "is-descriptor": "^1.0.0" }, @@ -5921,6 +6464,7 @@ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" } @@ -6188,9 +6732,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "funding": [ { "type": "opencollective", @@ -6205,10 +6749,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { @@ -6309,6 +6854,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "license": "MIT", "dependencies": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -6368,7 +6914,8 @@ "node_modules/call-me-maybe": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "license": "MIT" }, "node_modules/callsites": { "version": "3.1.0", @@ -6408,9 +6955,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001642", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", - "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "version": "1.0.30001664", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", + "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", "funding": [ { "type": "opencollective", @@ -6424,13 +6971,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/ccount": { "version": "2.0.1", @@ -6442,21 +6991,20 @@ } }, "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", "dev": true, + "license": "MIT", "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=12" } }, "node_modules/chalk": { @@ -6508,15 +7056,13 @@ } }, "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">= 16" } }, "node_modules/check-more-types": { @@ -6601,6 +7147,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "license": "MIT", "dependencies": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -6615,6 +7162,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "license": "MIT", "dependencies": { "is-descriptor": "^0.1.0" }, @@ -6626,6 +7174,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "license": "MIT", "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" @@ -6707,7 +7256,8 @@ "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "peer": true }, "node_modules/clipboardy": { "version": "1.2.2", @@ -6903,6 +7453,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "license": "MIT", "dependencies": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" @@ -6977,10 +7528,18 @@ "node": ">=4.0.0" } }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "dev": true, + "license": "MIT" + }, "node_modules/complex.js": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz", "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==", + "license": "MIT", "engines": { "node": "*" }, @@ -6993,6 +7552,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -7031,7 +7591,8 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", @@ -7041,8 +7602,7 @@ "node_modules/confbox": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", - "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", - "dev": true + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==" }, "node_modules/console-browserify": { "version": "1.2.0", @@ -7099,6 +7659,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7131,6 +7692,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", "dependencies": { "layout-base": "^1.0.0" } @@ -7322,21 +7884,21 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/cypress": { - "version": "12.17.4", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.4.tgz", - "integrity": "sha512-gAN8Pmns9MA5eCDFSDJXWKUpaL3IDd89N9TtIupjYnzLSmlpVr+ZR+vb4U/qaMp+lB6tBvAmt7504c3Z4RU5KQ==", + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.15.0.tgz", + "integrity": "sha512-53aO7PwOfi604qzOkCSzNlWquCynLlKE/rmmpSPcziRH6LNfaDUAklQT6WJIsD8ywxlIy+uVZsnTMCCQVd2kTw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { - "@cypress/request": "2.88.12", + "@cypress/request": "^3.0.4", "@cypress/xvfb": "^1.2.4", - "@types/node": "^16.18.39", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "arch": "^2.2.0", "blob-util": "^2.0.2", "bluebird": "^3.7.2", - "buffer": "^5.6.0", + "buffer": "^5.7.1", "cachedir": "^2.3.0", "chalk": "^4.1.0", "check-more-types": "^2.24.0", @@ -7354,7 +7916,7 @@ "figures": "^3.2.0", "fs-extra": "^9.1.0", "getos": "^3.2.1", - "is-ci": "^3.0.0", + "is-ci": "^3.0.1", "is-installed-globally": "~0.4.0", "lazy-ass": "^1.6.0", "listr2": "^3.8.3", @@ -7368,7 +7930,7 @@ "request-progress": "^3.0.0", "semver": "^7.5.3", "supports-color": "^8.1.1", - "tmp": "~0.2.1", + "tmp": "~0.2.3", "untildify": "^4.0.0", "yauzl": "^2.10.0" }, @@ -7376,7 +7938,7 @@ "cypress": "bin/cypress" }, "engines": { - "node": "^14.0.0 || ^16.0.0 || >=18.0.0" + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" } }, "node_modules/cypress-multi-reporters": { @@ -7397,10 +7959,11 @@ } }, "node_modules/cypress-parallel": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/cypress-parallel/-/cypress-parallel-0.13.0.tgz", - "integrity": "sha512-tTsYad23u+OpwsU/LFaBfY4rukBuEtkh1j2geLIT4n6hHbEx/ubLk5rV7uKrdhc4SArn/3nOZfkXW8bQT8+8gw==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/cypress-parallel/-/cypress-parallel-0.14.0.tgz", + "integrity": "sha512-Lsh28G70vxjL0cjR820BdaVQHnGc17Vvb+tYmjbRPmfC+XEzwvUzhcaD0E1zCztBSYhw+b1/1JLmW4Y0qE/EDA==", "dev": true, + "license": "MIT", "dependencies": { "@colors/colors": "^1.5.0", "cli-table3": "^0.6.0", @@ -7703,16 +8266,11 @@ } }, "node_modules/cypress-wait-until": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-1.7.2.tgz", - "integrity": "sha512-uZ+M8/MqRcpf+FII/UZrU7g1qYZ4aVlHcgyVopnladyoBrpoaMJ4PKZDrdOJ05H5RHbr7s9Tid635X3E+ZLU/Q==", - "dev": true - }, - "node_modules/cypress/node_modules/@types/node": { - "version": "16.18.101", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.101.tgz", - "integrity": "sha512-AAsx9Rgz2IzG8KJ6tXd6ndNkVcu+GYB6U/SnFAaokSPNx2N7dcIIfnighYUNumvj6YS2q39Dejz5tT0NCV7CWA==", - "dev": true + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-3.0.2.tgz", + "integrity": "sha512-iemies796dD5CgjG5kV0MnpEmKSH+s7O83ZoJLVzuVbZmm4lheMsZqAVT73hlMx4QlkwhxbyUzhOBUOZwoOe0w==", + "dev": true, + "license": "MIT" }, "node_modules/cypress/node_modules/chalk": { "version": "4.1.2", @@ -7755,9 +8313,10 @@ } }, "node_modules/cytoscape": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.0.tgz", - "integrity": "sha512-l590mjTHT6/Cbxp13dGPC2Y7VXdgc+rUeF8AnF/JPzhjNevbDJfObnJgaSjlldOgBQZbue+X6IUZ7r5GAgvauQ==", + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.2.tgz", + "integrity": "sha512-oICxQsjW8uSaRmn4UK/jkczKOqTrVqt5/1WL0POiJUT2EKNc9STM4hYFHv917yu55aTBMFNRzymlJhVAiWPCxw==", + "license": "MIT", "engines": { "node": ">=0.10" } @@ -7766,6 +8325,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", "dependencies": { "cose-base": "^1.0.0" }, @@ -7773,10 +8333,38 @@ "cytoscape": "^3.2.0" } }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, "node_modules/d3": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", "dependencies": { "d3-array": "3", "d3-axis": "3", @@ -7817,6 +8405,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", "dependencies": { "internmap": "1 - 2" }, @@ -7828,6 +8417,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", "engines": { "node": ">=12" } @@ -7836,6 +8426,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", @@ -7851,6 +8442,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", "dependencies": { "d3-path": "1 - 3" }, @@ -7862,6 +8454,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -7870,6 +8463,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", "dependencies": { "d3-array": "^3.2.0" }, @@ -7881,6 +8475,7 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", "dependencies": { "delaunator": "5" }, @@ -7892,6 +8487,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", "engines": { "node": ">=12" } @@ -7900,6 +8496,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" @@ -7912,6 +8509,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", "dependencies": { "commander": "7", "iconv-lite": "0.6", @@ -7936,6 +8534,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", "engines": { "node": ">= 10" } @@ -7944,6 +8543,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", "engines": { "node": ">=12" } @@ -7952,6 +8552,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", "dependencies": { "d3-dsv": "1 - 3" }, @@ -7963,6 +8564,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", @@ -7976,6 +8578,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -7984,6 +8587,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", "dependencies": { "d3-array": "2.5.0 - 3" }, @@ -7995,6 +8599,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -8003,6 +8608,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", "dependencies": { "d3-color": "1 - 3" }, @@ -8014,6 +8620,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", "engines": { "node": ">=12" } @@ -8022,6 +8629,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", "engines": { "node": ">=12" } @@ -8030,6 +8638,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", "engines": { "node": ">=12" } @@ -8038,6 +8647,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", "engines": { "node": ">=12" } @@ -8046,6 +8656,7 @@ "version": "0.12.3", "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" @@ -8055,6 +8666,7 @@ "version": "2.12.1", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", "dependencies": { "internmap": "^1.0.0" } @@ -8062,12 +8674,14 @@ "node_modules/d3-sankey/node_modules/d3-path": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" }, "node_modules/d3-sankey/node_modules/d3-shape": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", "dependencies": { "d3-path": "1" } @@ -8075,12 +8689,14 @@ "node_modules/d3-sankey/node_modules/internmap": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" }, "node_modules/d3-scale": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", @@ -8096,6 +8712,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" @@ -8108,6 +8725,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", "engines": { "node": ">=12" } @@ -8116,6 +8734,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", "dependencies": { "d3-path": "^3.1.0" }, @@ -8127,6 +8746,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", "dependencies": { "d3-array": "2 - 3" }, @@ -8138,6 +8758,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", "dependencies": { "d3-time": "1 - 3" }, @@ -8149,6 +8770,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", "engines": { "node": ">=12" } @@ -8157,6 +8779,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", @@ -8175,6 +8798,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", @@ -8190,6 +8814,7 @@ "version": "7.0.10", "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", + "license": "MIT", "dependencies": { "d3": "^7.8.2", "lodash-es": "^4.17.21" @@ -8200,6 +8825,7 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" }, @@ -8280,14 +8906,16 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -8298,6 +8926,12 @@ } } }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -8328,18 +8962,17 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", "engines": { "node": ">=0.10" } }, "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, + "license": "MIT", "engines": { "node": ">=6" } @@ -8403,6 +9036,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "license": "MIT", "dependencies": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" @@ -8415,6 +9049,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", "dependencies": { "robust-predicates": "^3.0.2" } @@ -8474,6 +9109,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", + "license": "MIT", "engines": { "node": ">=4" } @@ -8511,17 +9147,10 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, + "peer": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.3.1" } }, "node_modules/diffie-hellman": { @@ -8545,6 +9174,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "license": "MIT", "dependencies": { "path-type": "^3.0.0" }, @@ -8556,6 +9186,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "license": "MIT", "dependencies": { "pify": "^3.0.0" }, @@ -8567,6 +9198,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", "engines": { "node": ">=4" } @@ -8582,6 +9214,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -8602,9 +9235,10 @@ } }, "node_modules/dompurify": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", - "integrity": "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==" + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", + "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==", + "license": "(MPL-2.0 OR Apache-2.0)" }, "node_modules/duplexify": { "version": "3.7.1", @@ -8665,6 +9299,7 @@ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, + "license": "MIT", "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -8690,14 +9325,10 @@ "integrity": "sha512-9xUSSj7qcUxz+0r4X3+bwUNttEfGfK5AH+LVa1aTpqdAfrN5VhROYCfcF+up4hp5OL7IUKcZJJrzAGipQRDoiQ==" }, "node_modules/electron-to-chromium": { - "version": "1.4.828", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.828.tgz", - "integrity": "sha512-QOIJiWpQJDHAVO4P58pwb133Cwee0nbvy/MV1CwzZVGpkH1RX33N3vsaWRCpR6bF63AAq366neZrRTu7Qlsbbw==" - }, - "node_modules/elkjs": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", - "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==" + "version": "1.5.29", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", + "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==", + "license": "ISC" }, "node_modules/elliptic": { "version": "6.5.5", @@ -8991,7 +9622,8 @@ "node_modules/escape-latex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", - "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==", + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -9005,16 +9637,17 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -9060,15 +9693,15 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.34.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.4.tgz", - "integrity": "sha512-Np+jo9bUwJNxCsT12pXtrGhJgT3T44T1sHhn1Ssr42XFn8TES0267wPGo5nNrMHi8qkyimDAX2BUmkf9pSaVzA==", + "version": "7.37.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.0.tgz", + "integrity": "sha512-IHBePmfWH5lKhJnJ7WB1V+v/GolbB0rjS8XYVCSQCZKaQCAUhMoVoOEn1Ef8Z8Wf0a7l8KTJvuZg5/e4qrZ6nA==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.0.19", @@ -9089,7 +9722,7 @@ "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react-hooks": { @@ -9105,10 +9738,11 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.8.tgz", - "integrity": "sha512-MIKAclwaDFIiYtVBLzDdm16E+Ty4GwhB6wZlCAG1R3Ur+F9Qbo6PRxpA5DK7XtDgm+WlCoAY2WxAwqhmIDHg6Q==", + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.12.tgz", + "integrity": "sha512-9neVjoGv20FwYtCP6CB1dzR1vr57ZDNOXst21wd2xJ/cTlM2xLq0GWVlSNTdMn/4BtP6cHYBMCSp1wFBJ9jBsg==", "dev": true, + "license": "MIT", "peerDependencies": { "eslint": ">=7" } @@ -9130,6 +9764,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -9174,6 +9809,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -9201,6 +9837,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -9226,6 +9863,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -9267,6 +9905,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -9450,6 +10089,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "license": "MIT", "dependencies": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -9467,6 +10107,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -9475,6 +10116,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "license": "MIT", "dependencies": { "is-descriptor": "^0.1.0" }, @@ -9486,6 +10128,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "license": "MIT", "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" @@ -9497,7 +10140,8 @@ "node_modules/expand-brackets/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/extend": { "version": "3.0.2", @@ -9519,6 +10163,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "license": "MIT", "dependencies": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -9537,6 +10182,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "license": "MIT", "dependencies": { "is-descriptor": "^1.0.0" }, @@ -9571,7 +10217,8 @@ "dev": true, "engines": [ "node >=0.6.0" - ] + ], + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -9617,7 +10264,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -9625,6 +10273,13 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "dev": true, + "license": "MIT" + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -9684,6 +10339,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -9739,6 +10395,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -9752,7 +10409,8 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/flexsearch": { "version": "0.7.43", @@ -9770,11 +10428,6 @@ "node": ">=10" } }, - "node_modules/focus-visible": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.2.0.tgz", - "integrity": "sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==" - }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", @@ -9807,6 +10460,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9844,22 +10498,23 @@ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "*" } }, "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" } }, "node_modules/format": { @@ -9886,6 +10541,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "license": "MIT", "dependencies": { "map-cache": "^0.2.2" }, @@ -9957,7 +10613,8 @@ "node_modules/fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "license": "MIT" }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -10035,6 +10692,7 @@ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -10107,6 +10765,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10125,6 +10784,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" } @@ -10178,7 +10838,8 @@ "node_modules/glob-to-regexp": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==" + "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", + "license": "BSD" }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", @@ -10247,6 +10908,7 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "license": "MIT", "dependencies": { "@types/glob": "^7.1.1", "array-union": "^1.0.2", @@ -10265,6 +10927,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -10273,6 +10936,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "license": "MIT", "dependencies": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -10293,6 +10957,7 @@ "version": "2.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "license": "MIT", "dependencies": { "@mrmlnc/readdir-enhanced": "^2.2.1", "@nodelib/fs.stat": "^1.1.2", @@ -10309,6 +10974,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "license": "MIT", "dependencies": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -10324,6 +10990,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10343,6 +11010,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "license": "ISC", "dependencies": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -10352,6 +11020,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.0" }, @@ -10363,19 +11032,16 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "license": "MIT", "engines": { "node": ">= 4" } }, - "node_modules/globby/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "node_modules/globby/node_modules/is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4" }, @@ -10387,6 +11053,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "license": "MIT", "dependencies": { "kind-of": "^3.0.2" }, @@ -10398,6 +11065,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", "dependencies": { "is-buffer": "^1.1.5" }, @@ -10409,6 +11077,7 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "license": "MIT", "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -10432,6 +11101,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "license": "MIT", "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -10444,6 +11114,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", "engines": { "node": ">=6" } @@ -10452,6 +11123,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "license": "MIT", "engines": { "node": ">=6" } @@ -10460,6 +11132,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "license": "MIT", "dependencies": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -10497,7 +11170,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/gray-matter": { "version": "4.0.3", @@ -10559,6 +11233,12 @@ "gunzip-maybe": "bin.js" } }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, "node_modules/hamt_plus": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz", @@ -10658,6 +11338,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "license": "MIT", "dependencies": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -10671,6 +11352,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "license": "MIT", "dependencies": { "is-number": "^3.0.0", "kind-of": "^4.0.0" @@ -10679,15 +11361,11 @@ "node": ">=0.10.0" } }, - "node_modules/has-values/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "node_modules/has-values/node_modules/is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "license": "MIT", "dependencies": { "kind-of": "^3.0.2" }, @@ -10699,6 +11377,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", "dependencies": { "is-buffer": "^1.1.5" }, @@ -10710,6 +11389,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "license": "MIT", "dependencies": { "is-buffer": "^1.1.5" }, @@ -10721,6 +11401,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "license": "MIT", "engines": { "node": ">=8" } @@ -10899,6 +11580,29 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-html": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", + "integrity": "sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-jsx-runtime": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", @@ -10957,9 +11661,10 @@ } }, "node_modules/hast-util-to-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", - "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" }, @@ -11047,7 +11752,8 @@ "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "license": "ISC" }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", @@ -11122,6 +11828,7 @@ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -11147,14 +11854,15 @@ } }, "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", + "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", "dev": true, + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^2.0.2", - "sshpk": "^1.14.1" + "sshpk": "^1.18.0" }, "engines": { "node": ">=0.10" @@ -11234,10 +11942,11 @@ ] }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -11268,6 +11977,7 @@ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11336,15 +12046,11 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", "engines": { "node": ">=12" } }, - "node_modules/intersection-observer": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz", - "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==" - }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -11357,6 +12063,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", + "license": "MIT", "dependencies": { "hasown": "^2.0.0" }, @@ -11479,26 +12186,10 @@ } }, "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" }, "node_modules/is-callable": { "version": "1.2.7", @@ -11542,6 +12233,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", + "license": "MIT", "dependencies": { "hasown": "^2.0.0" }, @@ -11598,6 +12290,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", + "license": "MIT", "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" @@ -11830,6 +12523,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -11955,7 +12649,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-unicode-supported": { "version": "0.1.0", @@ -12013,6 +12708,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12044,6 +12740,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12061,7 +12758,8 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/iterator.prototype": { "version": "1.1.2", @@ -12094,7 +12792,8 @@ "node_modules/javascript-natural-sort": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", + "license": "MIT" }, "node_modules/jiti": { "version": "1.21.6", @@ -12109,7 +12808,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -12132,13 +12832,15 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jsdom": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz", - "integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==", + "version": "24.1.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz", + "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", "dev": true, + "license": "MIT", "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", @@ -12146,11 +12848,11 @@ "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.4", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.10", + "nwsapi": "^2.2.12", "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.0", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.4", @@ -12159,7 +12861,7 @@ "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", - "ws": "^8.17.0", + "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "engines": { @@ -12174,20 +12876,6 @@ } } }, - "node_modules/jsdom/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -12203,7 +12891,8 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -12214,13 +12903,15 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -12240,7 +12931,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/json5": { "version": "2.2.3", @@ -12279,6 +12971,7 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -12395,6 +13088,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -12412,14 +13106,6 @@ "node": ">=0.10.0" } }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/koa": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/koa/-/koa-2.15.3.tgz", @@ -12602,13 +13288,55 @@ "node_modules/kolorist": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", - "dev": true + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==" + }, + "node_modules/langium": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.0.0.tgz", + "integrity": "sha512-+Ez9EoiByeoTu/2BXmEaZ06iPNXM6thWJp02KfBO/raSMyCJ4jw7AkWWa+zBCTm0+Tw1Fj9FOxdqSskyN5nAwg==", + "license": "MIT", + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/langium/node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/langium/node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } }, "node_modules/layout-base": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", - "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==" + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" }, "node_modules/lazy-ass": { "version": "1.6.0", @@ -12712,7 +13440,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", - "dev": true, "dependencies": { "mlly": "^1.4.2", "pkg-types": "^1.0.3" @@ -12747,7 +13474,8 @@ "node_modules/lodash-es": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -12755,18 +13483,6 @@ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "dev": true - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -12921,10 +13637,11 @@ } }, "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", "dev": true, + "license": "MIT", "dependencies": { "get-func-name": "^2.0.1" } @@ -12950,6 +13667,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "license": "MIT", "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -12962,6 +13680,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", "engines": { "node": ">=6" } @@ -12970,6 +13689,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -12978,6 +13698,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -12986,6 +13707,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "license": "MIT", "dependencies": { "object-visit": "^1.0.0" }, @@ -13013,18 +13735,31 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/marked": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz", + "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/math-expressions": { - "version": "2.0.0-alpha66", - "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha66.tgz", - "integrity": "sha512-f05t5XuOp8xScfSB//EnRJVYs2ZUTRNXK9bdquWIB4esyRyXVhqxJtvjMS1Eno1lAou44cW3GrNnwje7gsSFYw==", + "version": "2.0.0-alpha68", + "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha68.tgz", + "integrity": "sha512-PfOzxkfxj7U2F0UiBFFSzXVaWoroRG9DIZTUljqmlD/HM/jGxn2ofPLe4Y5dZhk8eSQXXa2dfsAozBrnC/ky8Q==", + "license": "(GPL-3.0 OR Apache-2.0)", "dependencies": { - "@babel/cli": "^7.0.0", + "@babel/cli": "^7.25.6", "babel-upgrade": "^1.0.1", - "mathjs": "^10.6.4", - "number-theory": "*", - "numeric": "*", + "mathjs": "^13.1.1", + "number-theory": "1.1.0", + "numeric": "1.2.6", "seedrandom": "^3.0.5", - "xml-parser": "*" + "xml-parser": "1.2.1" } }, "node_modules/mathjax-full": { @@ -13039,25 +13774,26 @@ } }, "node_modules/mathjs": { - "version": "10.6.4", - "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-10.6.4.tgz", - "integrity": "sha512-omQyvRE1jIy+3k2qsqkWASOcd45aZguXZDckr3HtnTYyXk5+2xpVfC3kATgbO2Srjxlqww3TVdhD0oUdZ/hiFA==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-13.2.0.tgz", + "integrity": "sha512-P5PZoiUX2Tkghkv3tsSqlK0B9My/ErKapv1j6wdxd0MOrYQ30cnGE4LH/kzYB2gA5rN46Njqc4cFgJjaxgijoQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/runtime": "^7.18.6", + "@babel/runtime": "^7.25.6", "complex.js": "^2.1.1", - "decimal.js": "^10.3.1", + "decimal.js": "^10.4.3", "escape-latex": "^1.2.0", - "fraction.js": "^4.2.0", + "fraction.js": "^4.3.7", "javascript-natural-sort": "^0.7.1", "seedrandom": "^3.0.5", "tiny-emitter": "^2.1.0", - "typed-function": "^2.1.0" + "typed-function": "^4.2.1" }, "bin": { "mathjs": "bin/cli.js" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/md5.js": { @@ -13423,84 +14159,54 @@ } }, "node_modules/mermaid": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.1.tgz", - "integrity": "sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA==", - "dependencies": { - "@braintree/sanitize-url": "^6.0.1", - "@types/d3-scale": "^4.0.3", - "@types/d3-scale-chromatic": "^3.0.0", - "cytoscape": "^3.28.1", + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.2.1.tgz", + "integrity": "sha512-F8TEaLVVyxTUmvKswVFyOkjPrlJA5h5vNR1f7ZnSWSpqxgEZG1hggtn/QCa7znC28bhlcrNh10qYaIiill7q4A==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.0.1", + "@iconify/utils": "^2.1.32", + "@mermaid-js/parser": "^0.3.0", + "cytoscape": "^3.29.2", "cytoscape-cose-bilkent": "^4.1.0", - "d3": "^7.4.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.10", - "dayjs": "^1.11.7", - "dompurify": "^3.0.5", - "elkjs": "^0.9.0", + "dayjs": "^1.11.10", + "dompurify": "^3.0.11", "katex": "^0.16.9", - "khroma": "^2.0.0", + "khroma": "^2.1.0", "lodash-es": "^4.17.21", - "mdast-util-from-markdown": "^1.3.0", - "non-layered-tidy-tree-layout": "^2.0.2", - "stylis": "^4.1.3", + "marked": "^13.0.2", + "roughjs": "^4.6.6", + "stylis": "^4.3.1", "ts-dedent": "^2.2.0", - "uuid": "^9.0.0", - "web-worker": "^1.2.0" - } - }, - "node_modules/mermaid/node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", - "dependencies": { - "@types/unist": "^2" + "uuid": "^9.0.1" } }, - "node_modules/mermaid/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, - "node_modules/mermaid/node_modules/mdast-util-from-markdown": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", - "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "mdast-util-to-string": "^3.1.0", - "micromark": "^3.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-decode-string": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/mermaid/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/mermaid/node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "node_modules/mhchemparser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.2.1.tgz", + "integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==" }, - "node_modules/mermaid/node_modules/micromark": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13515,26 +14221,26 @@ "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", - "micromark-core-commonmark": "^1.0.1", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/mermaid/node_modules/micromark-core-commonmark": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", - "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", "funding": [ { "type": "GitHub Sponsors", @@ -13547,514 +14253,55 @@ ], "dependencies": { "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/mermaid/node_modules/micromark-factory-destination": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", - "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mermaid/node_modules/micromark-factory-label": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", - "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/mermaid/node_modules/micromark-factory-space": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-factory-title": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", - "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-factory-whitespace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", - "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-chunked": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-classify-character": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-combine-extensions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", - "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-decode-numeric-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", - "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-decode-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", - "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mermaid/node_modules/micromark-util-html-tag-name": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", - "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mermaid/node_modules/micromark-util-normalize-identifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-resolve-all": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-subtokenize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", - "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "node_modules/mermaid/node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mermaid/node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/mermaid/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mermaid/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mhchemparser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.2.1.tgz", - "integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==" - }, - "node_modules/micromark": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", - "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", - "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-frontmatter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", - "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", - "dependencies": { - "fault": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/micromark-extension-gfm-autolink-literal": { @@ -14775,6 +15022,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "license": "MIT", "dependencies": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -14787,6 +15035,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4" }, @@ -14818,7 +15067,6 @@ "version": "1.7.1", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", - "dev": true, "dependencies": { "acorn": "^8.11.3", "pathe": "^1.1.2", @@ -15023,24 +15271,18 @@ "node": ">= 0.8" } }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "engines": { - "node": ">=4" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/muggle-string": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", - "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", - "dev": true + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" }, "node_modules/mz": { "version": "2.7.0", @@ -15074,6 +15316,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "license": "MIT", "dependencies": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -15095,6 +15338,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "license": "MIT", "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -15107,6 +15351,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4" }, @@ -15217,17 +15462,18 @@ } }, "node_modules/nextra": { - "version": "3.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/nextra/-/nextra-3.0.0-alpha.25.tgz", - "integrity": "sha512-vikr4bJm75j9V5kMWxmUMphDDaoTxRUvdImmKPhIFd+Fg0LYJJJnpuuV4mf7w0I8uPlfob8ETRK1j776GKAMRw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/nextra/-/nextra-3.0.1.tgz", + "integrity": "sha512-aNcUrg5wP7NhupkQDh7uPubx6aJWCQijdrmFuOFBRFMzQOXXIEYQ6W0Qp5hEDQ4LLNibVjqAy+p+j/HAhBoTpA==", + "license": "MIT", "dependencies": { - "@headlessui/react": "^1.7.17", + "@headlessui/react": "^2.1.2", "@mdx-js/mdx": "^3.0.0", "@mdx-js/react": "^3.0.0", "@napi-rs/simple-git": "^0.1.9", "@shikijs/twoslash": "^1.0.0", - "@theguild/remark-mermaid": "^0.0.5", - "@theguild/remark-npm2yarn": "0.3.0", + "@theguild/remark-mermaid": "^0.1.2", + "@theguild/remark-npm2yarn": "^0.3.2", "better-react-mathjax": "^2.0.3", "clsx": "^2.0.0", "estree-util-to-js": "^2.0.0", @@ -15237,15 +15483,15 @@ "gray-matter": "^4.0.3", "hast-util-to-estree": "^3.1.0", "katex": "^0.16.9", - "p-limit": "^4.0.0", + "p-limit": "^6.0.0", "rehype-katex": "^7.0.0", - "rehype-pretty-code": "0.13.0", + "rehype-pretty-code": "0.14.0", "rehype-raw": "^7.0.0", "remark-frontmatter": "^5.0.0", "remark-gfm": "^4.0.0", "remark-math": "^6.0.0", "remark-reading-time": "^2.0.1", - "remark-smartypants": "^2.1.0", + "remark-smartypants": "^3.0.0", "shiki": "^1.0.0", "slash": "^5.1.0", "title": "^3.5.3", @@ -15253,38 +15499,36 @@ "unist-util-visit": "^5.0.0", "yaml": "^2.3.2", "zod": "^3.22.3", - "zod-validation-error": "^1.5.0" + "zod-validation-error": "^3.0.0" }, "engines": { "node": ">=18" }, "peerDependencies": { "next": ">=13", - "react": ">=16.13.1", - "react-dom": ">=16.13.1" + "react": ">=18.0.0", + "react-dom": ">=18.0.0" } }, "node_modules/nextra-theme-docs": { - "version": "3.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/nextra-theme-docs/-/nextra-theme-docs-3.0.0-alpha.25.tgz", - "integrity": "sha512-1B9CyQW0Cs+H7En9ZN+qoFP4wHrmdMolzLX3LUdBzypHevu2YjN5p6f5JzvORdf92yUBEmCEaUD69C0N/Rmx6g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/nextra-theme-docs/-/nextra-theme-docs-3.0.1.tgz", + "integrity": "sha512-G7+zrJkCrHI8QPwO8korQCYDtJnOJjouaThJlRGHSYvanH6OxfFt9ecCadY9Ox8Isn0ZSbf0JUI8/X2/sxTVMw==", + "license": "MIT", "dependencies": { - "@headlessui/react": "^1.7.17", - "@popperjs/core": "^2.11.8", + "@headlessui/react": "^2.1.2", "clsx": "^2.0.0", "escape-string-regexp": "^5.0.0", "flexsearch": "^0.7.43", - "focus-visible": "^5.2.0", - "intersection-observer": "^0.12.2", "next-themes": "^0.3.0", "scroll-into-view-if-needed": "^3.1.0", "zod": "^3.22.3" }, "peerDependencies": { "next": ">=13", - "nextra": "3.0.0-alpha.25", - "react": ">=16.13.1", - "react-dom": ">=16.13.1" + "nextra": "3.0.1", + "react": ">=18.0.0", + "react-dom": ">=18.0.0" } }, "node_modules/nextra-theme-docs/node_modules/escape-string-regexp": { @@ -15301,14 +15545,16 @@ "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "license": "MIT" }, "node_modules/nlcst-to-string": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-3.1.1.tgz", - "integrity": "sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "license": "MIT", "dependencies": { - "@types/nlcst": "^1.0.0" + "@types/nlcst": "^2.0.0" }, "funding": { "type": "opencollective", @@ -15316,15 +15562,17 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "license": "MIT" }, "node_modules/node-stdlib-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.2.0.tgz", - "integrity": "sha512-VSjFxUhRhkyed8AtLwSCkMrJRfQ3e2lGtG3sP6FEgaLKBBbxM/dLfjRe1+iLhjvyLFW3tBQ8+c0pcOtXGbAZJg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.2.1.tgz", + "integrity": "sha512-dZezG3D88Lg22DwyjsDuUs7cCT/XGr8WwJgg/S3ZnkcWuPet2Tt/W1d2Eytb1Z73JpZv+XVCDI5TWv6UMRq0Gg==", "dev": true, + "license": "MIT", "dependencies": { "assert": "^2.0.0", "browser-resolve": "^2.0.0", @@ -15350,7 +15598,7 @@ "string_decoder": "^1.0.0", "timers-browserify": "^2.0.4", "tty-browserify": "0.0.1", - "url": "^0.11.0", + "url": "^0.11.4", "util": "^0.12.4", "vm-browserify": "^1.0.1" }, @@ -15373,15 +15621,11 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, - "node_modules/non-layered-tidy-tree-layout": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", - "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" - }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -15393,6 +15637,7 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -15409,6 +15654,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", "bin": { "semver": "bin/semver" } @@ -15444,9 +15690,10 @@ } }, "node_modules/npm-to-yarn": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-2.2.1.tgz", - "integrity": "sha512-O/j/ROyX0KGLG7O6Ieut/seQ0oiTpHF2tXAcFbpdTLQFiaNtkyTXXocM1fwpaa60dg1qpWj0nHlbNhx6qwuENQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-3.0.0.tgz", + "integrity": "sha512-76YnmsbfrYp0tMsWxM0RNX0Vs+x8JxpJGu6B/jDn4lW8+laiTcKmKi9MeMh4UikO4RkJ1oqURoDy9bXJmMXS6A==", + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -15496,6 +15743,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "license": "MIT", "dependencies": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -15509,6 +15757,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "license": "MIT", "dependencies": { "is-descriptor": "^0.1.0" }, @@ -15516,15 +15765,11 @@ "node": ">=0.10.0" } }, - "node_modules/object-copy/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "node_modules/object-copy/node_modules/is-descriptor": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "license": "MIT", "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" @@ -15537,6 +15782,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", "dependencies": { "is-buffer": "^1.1.5" }, @@ -15594,6 +15840,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "license": "MIT", "dependencies": { "isobject": "^3.0.0" }, @@ -15655,6 +15902,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -15723,6 +15971,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oniguruma-to-js": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", + "integrity": "sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==", + "license": "MIT", + "dependencies": { + "regex": "^4.3.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/only": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", @@ -15916,14 +16176,15 @@ } }, "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz", + "integrity": "sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==", + "license": "MIT", "dependencies": { - "yocto-queue": "^1.0.0" + "yocto-queue": "^1.1.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -16000,6 +16261,12 @@ "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", "dev": true }, + "node_modules/package-manager-detector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.0.tgz", + "integrity": "sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==", + "license": "MIT" + }, "node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -16076,13 +16343,17 @@ } }, "node_modules/parse-latin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-5.0.1.tgz", - "integrity": "sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "license": "MIT", "dependencies": { - "nlcst-to-string": "^3.0.0", - "unist-util-modify-children": "^3.0.0", - "unist-util-visit-children": "^2.0.0" + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" }, "funding": { "type": "github", @@ -16092,7 +16363,8 @@ "node_modules/parse-numeric-range": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", - "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", + "license": "ISC" }, "node_modules/parse5": { "version": "7.1.2", @@ -16118,6 +16390,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -16128,10 +16401,17 @@ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "dev": true }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, "node_modules/path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==" + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "license": "MIT" }, "node_modules/path-exists": { "version": "4.0.0", @@ -16187,10 +16467,11 @@ "dev": true }, "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", - "dev": true + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", @@ -16204,16 +16485,16 @@ "node_modules/pathe": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==" }, "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">= 14.16" } }, "node_modules/pbkdf2": { @@ -16277,7 +16558,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/periscopic": { "version": "3.1.0", @@ -16298,9 +16580,10 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -16352,7 +16635,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.3.tgz", "integrity": "sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==", - "dev": true, "dependencies": { "confbox": "^0.1.7", "mlly": "^1.7.1", @@ -16366,12 +16648,13 @@ "dev": true }, "node_modules/playwright": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.2.tgz", - "integrity": "sha512-ReywF2t/0teRvNBpfIgh5e4wnrI/8Su8ssdo5XsQKpjxJj+jspm00jSoz9BTg91TT0c9HRjXO7LBNVrgYj9X0g==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", + "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.45.2" + "playwright-core": "1.47.2" }, "bin": { "playwright": "cli.js" @@ -16384,10 +16667,11 @@ } }, "node_modules/playwright-core": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.2.tgz", - "integrity": "sha512-ha175tAWb0dTK0X4orvBIqi3jGEt701SMxMhyujxNrgd8K0Uy5wMSwwcQHtyB4om7INUkfndx02XnQ2p6dvLDw==", + "version": "1.47.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", + "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -16401,6 +16685,7 @@ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -16409,10 +16694,27 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "node_modules/posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -16427,9 +16729,9 @@ } }, "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -16445,10 +16747,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -16638,38 +16941,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, "node_modules/prismjs": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", @@ -16795,15 +17066,17 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -17036,11 +17309,12 @@ } }, "node_modules/react-router": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.0.tgz", - "integrity": "sha512-bziKjCcDbcxgWS9WlWFcQIVZ2vJHnCP6DGpQDT0l+0PFDasfJKgzf9CM22eTyhFsZkjk8ApCdKjJwKtzqH80jQ==", + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.2.tgz", + "integrity": "sha512-tvN1iuT03kHgOFnLPfLJ8V95eijteveqdOSk+srqfePtQvqCExB8eHOYnlilbOcyJyKnYkr1vJvf7YqotAJu1A==", + "license": "MIT", "dependencies": { - "@remix-run/router": "1.18.0" + "@remix-run/router": "1.19.2" }, "engines": { "node": ">=14.0.0" @@ -17050,28 +17324,20 @@ } }, "node_modules/react-router-dom": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.0.tgz", - "integrity": "sha512-BhcczgDWWgvGZxjDDGuGHrA8HrsSudilqTaRSBYLWDayvo1ClchNIDVt5rldqp6e7Dro5dEFx9Mzc+r292lN0w==", + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.2.tgz", + "integrity": "sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==", + "license": "MIT", "dependencies": { - "@remix-run/router": "1.18.0", - "react-router": "6.25.0" + "@remix-run/router": "1.19.2", + "react-router": "6.26.2" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/react-simple-code-editor": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/react-simple-code-editor/-/react-simple-code-editor-0.13.1.tgz", - "integrity": "sha512-XYeVwRZwgyKtjNIYcAEgg2FaQcCZwhbarnkJIV20U2wkCU9q/CPFBo8nRXrK4GXUz3AvbqZFsZRrpUTkqqEYyQ==", - "peerDependencies": { - "react": "*", - "react-dom": "*" + "react-dom": ">=16.8" } }, "node_modules/react-style-singleton": { @@ -17130,6 +17396,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -17144,6 +17411,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-5.0.0.tgz", "integrity": "sha512-XBQjqOBtTzyol2CpsQOw8LHV0XbDZVG7xMMjmXAJomlVY03WOBRmYgDJETlvcg0H63AJvPRwT7GFi5rvOzUOKg==", + "license": "MIT", "dependencies": { "find-up": "^3.0.0", "read-pkg": "^5.0.0" @@ -17156,6 +17424,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", "dependencies": { "locate-path": "^3.0.0" }, @@ -17167,6 +17436,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -17179,6 +17449,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -17193,6 +17464,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", "dependencies": { "p-limit": "^2.0.0" }, @@ -17204,6 +17476,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", "engines": { "node": ">=4" } @@ -17212,6 +17485,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -17292,10 +17566,17 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, + "node_modules/regex": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.2.tgz", + "integrity": "sha512-kK/AA3A9K6q2js89+VMymcboLOlF5lZRCYJv3gzszXFHBr6kO6qLGzbm+UIugBEV8SMMKCTR59txoY6ctRHYVw==", + "license": "MIT" + }, "node_modules/regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "license": "MIT", "dependencies": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -17308,6 +17589,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "license": "MIT", "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -17320,6 +17602,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4" }, @@ -17369,9 +17652,10 @@ } }, "node_modules/rehype-parse": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.0.tgz", - "integrity": "sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "hast-util-from-html": "^2.0.0", @@ -17383,22 +17667,23 @@ } }, "node_modules/rehype-pretty-code": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.13.0.tgz", - "integrity": "sha512-+22dz1StXlF7dlMyOySNaVxgcGhMI4BCxq0JxJJPWYGiKsI6cu5jyuIKGHXHvH18D8sv1rdKtvsY9UEfN3++SQ==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.14.0.tgz", + "integrity": "sha512-hBeKF/Wkkf3zyUS8lal9RCUuhypDWLQc+h9UrP9Pav25FUm/AQAVh4m5gdvJxh4Oz+U+xKvdsV01p1LdvsZTiQ==", + "license": "MIT", "dependencies": { "@types/hast": "^3.0.4", "hast-util-to-string": "^3.0.0", "parse-numeric-range": "^1.3.0", "rehype-parse": "^9.0.0", - "unified": "^11.0.4", + "unified": "^11.0.5", "unist-util-visit": "^5.0.0" }, "engines": { "node": ">=18" }, "peerDependencies": { - "shiki": "^1.0.0" + "shiki": "^1.3.0" } }, "node_modules/rehype-raw": { @@ -17593,16 +17878,18 @@ } }, "node_modules/remark-smartypants": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-2.1.0.tgz", - "integrity": "sha512-qoF6Vz3BjU2tP6OfZqHOvCU0ACmu/6jhGaINSQRI9mM7wCxNQTKB3JUAN4SVoN2ybElEDTxBIABRep7e569iJw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "license": "MIT", "dependencies": { - "retext": "^8.1.0", - "retext-smartypants": "^5.2.0", + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", "unist-util-visit": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=16.0.0" } }, "node_modules/remark-stringify": { @@ -17623,6 +17910,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -17631,6 +17919,7 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "license": "MIT", "engines": { "node": ">=0.10" } @@ -17653,6 +17942,16 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -17684,446 +17983,159 @@ "resolve": "bin/resolve" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-path": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", - "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", - "dev": true, - "dependencies": { - "http-errors": "~1.6.2", - "path-is-absolute": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/resolve-path/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/resolve-path/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/resolve-path/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/resolve-path/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/resolve-path/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, - "node_modules/retext": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/retext/-/retext-8.1.0.tgz", - "integrity": "sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==", - "dependencies": { - "@types/nlcst": "^1.0.0", - "retext-latin": "^3.0.0", - "retext-stringify": "^3.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-latin": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-3.1.0.tgz", - "integrity": "sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==", - "dependencies": { - "@types/nlcst": "^1.0.0", - "parse-latin": "^5.0.0", - "unherit": "^3.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-latin/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, - "node_modules/retext-latin/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-latin/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-latin/node_modules/vfile": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", - "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", - "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-latin/node_modules/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-smartypants": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-5.2.0.tgz", - "integrity": "sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==", - "dependencies": { - "@types/nlcst": "^1.0.0", - "nlcst-to-string": "^3.0.0", - "unified": "^10.0.0", - "unist-util-visit": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-smartypants/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, - "node_modules/retext-smartypants/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-smartypants/node_modules/unist-util-is": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", - "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-smartypants/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-smartypants/node_modules/unist-util-visit": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", - "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.1.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-smartypants/node_modules/unist-util-visit-parents": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", - "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-smartypants/node_modules/vfile": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", - "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", - "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/retext-smartypants/node_modules/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" } }, - "node_modules/retext-stringify": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-3.1.0.tgz", - "integrity": "sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==", + "node_modules/resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", + "dev": true, "dependencies": { - "@types/nlcst": "^1.0.0", - "nlcst-to-string": "^3.0.0", - "unified": "^10.0.0" + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.8" } }, - "node_modules/retext-stringify/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, - "node_modules/retext-stringify/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/resolve-path/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "node_modules/retext-stringify/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "node_modules/resolve-path/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, "dependencies": { - "@types/unist": "^2.0.0" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.6" } }, - "node_modules/retext-stringify/node_modules/vfile": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", - "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", - "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/resolve-path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/resolve-path/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/resolve-path/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" } }, - "node_modules/retext-stringify/node_modules/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "license": "MIT" + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/retext/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "license": "MIT", + "engines": { + "node": ">=0.12" + } }, - "node_modules/retext/node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/retext/node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0" + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/retext/node_modules/vfile": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", - "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", + "node_modules/retext-smartypants": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.1.1.tgz", + "integrity": "sha512-onsHf34i/GzgElJgtT1K2V+31yEhWs7NJboKNxXJcmVMMPxLpgxZ9iADoMdydd6j/bHic5F/aNq0CGqElEtu2g==", + "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/retext/node_modules/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" }, "funding": { "type": "opencollective", @@ -18161,6 +18173,7 @@ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -18177,6 +18190,7 @@ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -18205,15 +18219,17 @@ "node_modules/robust-predicates": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" }, "node_modules/rollup": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", - "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", + "version": "4.22.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.5.tgz", + "integrity": "sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==", "dev": true, + "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -18223,22 +18239,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.1", - "@rollup/rollup-android-arm64": "4.18.1", - "@rollup/rollup-darwin-arm64": "4.18.1", - "@rollup/rollup-darwin-x64": "4.18.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", - "@rollup/rollup-linux-arm-musleabihf": "4.18.1", - "@rollup/rollup-linux-arm64-gnu": "4.18.1", - "@rollup/rollup-linux-arm64-musl": "4.18.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", - "@rollup/rollup-linux-riscv64-gnu": "4.18.1", - "@rollup/rollup-linux-s390x-gnu": "4.18.1", - "@rollup/rollup-linux-x64-gnu": "4.18.1", - "@rollup/rollup-linux-x64-musl": "4.18.1", - "@rollup/rollup-win32-arm64-msvc": "4.18.1", - "@rollup/rollup-win32-ia32-msvc": "4.18.1", - "@rollup/rollup-win32-x64-msvc": "4.18.1", + "@rollup/rollup-android-arm-eabi": "4.22.5", + "@rollup/rollup-android-arm64": "4.22.5", + "@rollup/rollup-darwin-arm64": "4.22.5", + "@rollup/rollup-darwin-x64": "4.22.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.22.5", + "@rollup/rollup-linux-arm-musleabihf": "4.22.5", + "@rollup/rollup-linux-arm64-gnu": "4.22.5", + "@rollup/rollup-linux-arm64-musl": "4.22.5", + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.5", + "@rollup/rollup-linux-riscv64-gnu": "4.22.5", + "@rollup/rollup-linux-s390x-gnu": "4.22.5", + "@rollup/rollup-linux-x64-gnu": "4.22.5", + "@rollup/rollup-linux-x64-musl": "4.22.5", + "@rollup/rollup-win32-arm64-msvc": "4.22.5", + "@rollup/rollup-win32-ia32-msvc": "4.22.5", + "@rollup/rollup-win32-x64-msvc": "4.22.5", "fsevents": "~2.3.2" } }, @@ -18389,6 +18405,18 @@ "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", "dev": true }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", @@ -18421,7 +18449,8 @@ "node_modules/rw": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" }, "node_modules/rxjs": { "version": "7.8.1", @@ -18432,17 +18461,6 @@ "tslib": "^2.1.0" } }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/safe-array-concat": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", @@ -18485,6 +18503,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "license": "MIT", "dependencies": { "ret": "~0.1.10" } @@ -18554,7 +18573,8 @@ "node_modules/seedrandom": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", + "license": "MIT" }, "node_modules/semver": { "version": "6.3.1", @@ -18616,6 +18636,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "license": "MIT", "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -18678,14 +18699,33 @@ } }, "node_modules/shiki": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz", - "integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.20.0.tgz", + "integrity": "sha512-MZJJ1PCFsQB1Piq+25wiz0a75yUv8Q3/fzy7SzRx5ONdjdtGdyiKwYn8vb/FnK5kjS0voWGnPpjG16POauUR+g==", + "license": "MIT", "dependencies": { - "@shikijs/core": "1.10.3", + "@shikijs/core": "1.20.0", + "@shikijs/engine-javascript": "1.20.0", + "@shikijs/engine-oniguruma": "1.20.0", + "@shikijs/types": "1.20.0", + "@shikijs/vscode-textmate": "^9.2.2", "@types/hast": "^3.0.4" } }, + "node_modules/shiki/node_modules/@shikijs/core": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.20.0.tgz", + "integrity": "sha512-KlO3iE0THzSdYkzDFugt8SHe6FR3qNYTkmpbdW1d6xo8juQkMjybxAw/cBi2npL2eb2F4PbbnSs5Z9tDusfvyg==", + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "1.20.0", + "@shikijs/engine-oniguruma": "1.20.0", + "@shikijs/types": "1.20.0", + "@shikijs/vscode-textmate": "^9.2.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.3" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -18744,6 +18784,7 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "license": "MIT", "dependencies": { "base": "^0.11.1", "debug": "^2.2.0", @@ -18762,6 +18803,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "license": "MIT", "dependencies": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -18775,6 +18817,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "license": "MIT", "dependencies": { "is-descriptor": "^1.0.0" }, @@ -18786,6 +18829,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "license": "MIT", "dependencies": { "kind-of": "^3.2.0" }, @@ -18793,15 +18837,11 @@ "node": ">=0.10.0" } }, - "node_modules/snapdragon-util/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "node_modules/snapdragon-util/node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", "dependencies": { "is-buffer": "^1.1.5" }, @@ -18813,6 +18853,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -18821,6 +18862,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "license": "MIT", "dependencies": { "is-descriptor": "^0.1.0" }, @@ -18832,6 +18874,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "license": "MIT", "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" @@ -18843,12 +18886,14 @@ "node_modules/snapdragon/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/snapdragon/node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -18857,6 +18902,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", + "license": "MIT", "dependencies": { "is-plain-obj": "^1.0.0" }, @@ -18868,6 +18914,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -18889,9 +18936,10 @@ } }, "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -18901,6 +18949,7 @@ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "license": "MIT", "dependencies": { "atob": "^2.1.2", "decode-uri-component": "^0.2.0", @@ -18913,7 +18962,8 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated" + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "license": "MIT" }, "node_modules/sourcemap-codec": { "version": "1.4.8", @@ -18935,6 +18985,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -18943,21 +18994,24 @@ "node_modules/spdx-exceptions": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", - "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==" + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "license": "CC0-1.0" }, "node_modules/speech-rule-engine": { "version": "4.0.7", @@ -18984,6 +19038,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "license": "MIT", "dependencies": { "extend-shallow": "^3.0.0" }, @@ -18995,6 +19050,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "license": "MIT", "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -19007,6 +19063,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4" }, @@ -19024,6 +19081,7 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, + "license": "MIT", "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -19054,6 +19112,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "license": "MIT", "dependencies": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -19066,6 +19125,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "license": "MIT", "dependencies": { "is-descriptor": "^0.1.0" }, @@ -19077,6 +19137,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "license": "MIT", "dependencies": { "is-accessor-descriptor": "^1.0.1", "is-data-descriptor": "^1.0.1" @@ -19090,6 +19151,7 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -19180,6 +19242,7 @@ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6.19" } @@ -19373,24 +19436,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", - "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", - "dev": true, - "dependencies": { - "js-tokens": "^9.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", - "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", - "dev": true - }, "node_modules/style-mod": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", @@ -19481,9 +19526,10 @@ } }, "node_modules/stylis": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", - "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", + "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==", + "license": "MIT" }, "node_modules/sucrase": { "version": "3.35.0", @@ -19560,10 +19606,11 @@ "dev": true }, "node_modules/tailwindcss": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.6.tgz", - "integrity": "sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", "dev": true, + "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -19758,25 +19805,44 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, "node_modules/tinybench": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", - "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", - "dev": true + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "license": "MIT" }, "node_modules/tinypool": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", - "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.0.0" } }, "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -19893,6 +19959,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "license": "MIT", "dependencies": { "kind-of": "^3.0.2" }, @@ -19900,15 +19967,11 @@ "node": ">=0.10.0" } }, - "node_modules/to-object-path/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "node_modules/to-object-path/node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "license": "MIT", "dependencies": { "is-buffer": "^1.1.5" }, @@ -19920,6 +19983,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "license": "MIT", "dependencies": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -19946,6 +20010,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "license": "MIT", "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -19958,6 +20023,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4" }, @@ -20055,6 +20121,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "license": "MIT", "engines": { "node": ">=6.10" } @@ -20100,6 +20167,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -20111,7 +20179,8 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true + "dev": true, + "license": "Unlicense" }, "node_modules/twoslash": { "version": "0.2.9", @@ -20142,15 +20211,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -20250,17 +20310,19 @@ } }, "node_modules/typed-function": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-2.1.0.tgz", - "integrity": "sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.2.1.tgz", + "integrity": "sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==", + "license": "MIT", "engines": { - "node": ">= 10" + "node": ">= 18" } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -20272,8 +20334,7 @@ "node_modules/ufo": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", - "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", - "dev": true + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==" }, "node_modules/unbox-primitive": { "version": "1.0.2", @@ -20297,17 +20358,8 @@ }, "node_modules/undici-types": { "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "node_modules/unherit": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-3.0.1.tgz", - "integrity": "sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unified": { "version": "11.0.5", @@ -20331,6 +20383,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "license": "MIT", "dependencies": { "arr-union": "^3.1.0", "get-value": "^2.0.6", @@ -20367,11 +20420,12 @@ } }, "node_modules/unist-util-modify-children": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-3.1.1.tgz", - "integrity": "sha512-yXi4Lm+TG5VG+qvokP6tpnk+r1EPwyYL04JWDxLvgvPV40jANh7nm3udk65OOWquvbMDe+PL9+LmkxDpTv/7BA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0", + "@types/unist": "^3.0.0", "array-iterate": "^2.0.0" }, "funding": { @@ -20379,11 +20433,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-modify-children/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, "node_modules/unist-util-position": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", @@ -20462,22 +20511,18 @@ } }, "node_modules/unist-util-visit-children": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-2.0.2.tgz", - "integrity": "sha512-+LWpMFqyUwLGpsQxpumsQ9o9DG2VGLFrpz+rpVXYIEdPy57GSy5HioC0g3bg/8WP9oCLlapQtklOzQ8uLS496Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0" + "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-visit-children/node_modules/@types/unist": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", - "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" - }, "node_modules/unist-util-visit-parents": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", @@ -20504,6 +20549,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "license": "MIT", "dependencies": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -20516,6 +20562,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "license": "MIT", "dependencies": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -20529,6 +20576,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "license": "MIT", "dependencies": { "isarray": "1.0.0" }, @@ -20540,6 +20588,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -20547,7 +20596,8 @@ "node_modules/unset-value/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, "node_modules/untildify": { "version": "4.0.0", @@ -20609,16 +20659,21 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "license": "MIT" }, "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^1.4.1", - "qs": "^6.11.2" + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/url-parse": { @@ -20631,25 +20686,11 @@ "requires-port": "^1.0.0" } }, - "node_modules/url/node_modules/qs": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", - "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -20700,6 +20741,7 @@ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", "dev": true, + "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -20728,45 +20770,21 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, - "node_modules/uvu": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", - "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, - "node_modules/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -20784,6 +20802,7 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -20831,14 +20850,15 @@ } }, "node_modules/vite": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.4.tgz", - "integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==", + "version": "5.4.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.21.3", - "postcss": "^8.4.39", - "rollup": "^4.13.0" + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" @@ -20857,6 +20877,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -20874,6 +20895,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -20886,15 +20910,15 @@ } }, "node_modules/vite-node": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", - "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", + "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", "dev": true, + "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", + "debug": "^4.3.6", + "pathe": "^1.1.2", "vite": "^5.0.0" }, "bin": { @@ -21338,18 +21362,21 @@ } }, "node_modules/vite-plugin-dts": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.9.1.tgz", - "integrity": "sha512-rVp2KM9Ue22NGWB8dNtWEr+KekN3rIgz1tWD050QnRGlriUCmaDwa7qA5zDEjbXg5lAXhYMSBJtx3q3hQIJZSg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-4.2.2.tgz", + "integrity": "sha512-USwTMReZFf8yXV+cKkm4WOMqmFjbReAvkyxON5xzdnZzJEBnFgax6BBDZIGGr9WMJYvhHdpaIHLrOjXDcla4OA==", "dev": true, + "license": "MIT", "dependencies": { - "@microsoft/api-extractor": "7.43.0", + "@microsoft/api-extractor": "7.47.7", "@rollup/pluginutils": "^5.1.0", - "@vue/language-core": "^1.8.27", - "debug": "^4.3.4", + "@volar/typescript": "^2.4.4", + "@vue/language-core": "2.1.6", + "compare-versions": "^6.1.1", + "debug": "^4.3.6", "kolorist": "^1.8.0", - "magic-string": "^0.30.8", - "vue-tsc": "^1.8.27" + "local-pkg": "^0.5.0", + "magic-string": "^0.30.11" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -21365,12 +21392,13 @@ } }, "node_modules/vite-plugin-dts/node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/vite-plugin-static-copy": { @@ -21812,31 +21840,31 @@ } }, "node_modules/vitest": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", - "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", + "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/expect": "1.6.0", - "@vitest/runner": "1.6.0", - "@vitest/snapshot": "1.6.0", - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "acorn-walk": "^8.3.2", - "chai": "^4.3.10", - "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.3", + "@vitest/expect": "2.1.1", + "@vitest/mocker": "2.1.1", + "@vitest/pretty-format": "^2.1.1", + "@vitest/runner": "2.1.1", + "@vitest/snapshot": "2.1.1", + "@vitest/spy": "2.1.1", + "@vitest/utils": "2.1.1", + "chai": "^5.1.1", + "debug": "^4.3.6", + "magic-string": "^0.30.11", + "pathe": "^1.1.2", + "std-env": "^3.7.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.0", + "tinypool": "^1.0.0", + "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "1.6.0", - "why-is-node-running": "^2.2.2" + "vite-node": "2.1.1", + "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" @@ -21850,8 +21878,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.6.0", - "@vitest/ui": "1.6.0", + "@vitest/browser": "2.1.1", + "@vitest/ui": "2.1.1", "happy-dom": "*", "jsdom": "*" }, @@ -21876,147 +21904,14 @@ } } }, - "node_modules/vitest/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/vitest/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/vitest/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/vitest/node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/vitest/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dev": true, + "license": "MIT", "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/vitest/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/vm-browserify": { @@ -22026,10 +21921,10 @@ "dev": true }, "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", - "dev": true, + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.1.tgz", + "integrity": "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ==", + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -22085,7 +21980,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", - "dev": true, "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, @@ -22097,7 +21991,6 @@ "version": "3.17.5", "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", - "dev": true, "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" @@ -22106,59 +21999,17 @@ "node_modules/vscode-languageserver-textdocument": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", - "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", - "dev": true + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" }, "node_modules/vscode-languageserver-types": { "version": "3.17.5", "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "dev": true + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" }, "node_modules/vscode-uri": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", - "dev": true - }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", - "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "dev": true, - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, - "node_modules/vue-tsc": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", - "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", - "dev": true, - "dependencies": { - "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.27", - "semver": "^7.5.4" - }, - "bin": { - "vue-tsc": "bin/vue-tsc.js" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/vue-tsc/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" }, "node_modules/w3c-keyname": { "version": "2.2.8", @@ -22186,11 +22037,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/web-worker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", - "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==" - }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -22356,10 +22202,15 @@ "integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==" }, "node_modules/wireit": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/wireit/-/wireit-0.14.5.tgz", - "integrity": "sha512-K4ka9YBpSyD6pmFZYTJd4VpPsAiPT6j/fOtLzYgnKWlPIMM7lAZjQQ30H7urO+Lqx1Wvrw88tQHBz4njy+lglg==", + "version": "0.14.9", + "resolved": "https://registry.npmjs.org/wireit/-/wireit-0.14.9.tgz", + "integrity": "sha512-hFc96BgyslfO1WGSzQqOVYd5N3TB+4u9w70L9GHR/T7SYjvFmeznkYMsRIjMLhPcVabCEYPW1vV66wmIVDs+dQ==", "dev": true, + "license": "Apache-2.0", + "workspaces": [ + "vscode-extension", + "website" + ], "dependencies": { "brace-expansion": "^4.0.0", "chokidar": "^3.5.3", @@ -22517,6 +22368,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "license": "MIT", "dependencies": { "mkdirp": "^0.5.1" }, @@ -22528,6 +22380,7 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", "dependencies": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", @@ -22538,6 +22391,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", + "license": "MIT", "dependencies": { "detect-indent": "^5.0.0", "graceful-fs": "^4.1.15", @@ -22554,6 +22408,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", "engines": { "node": ">=6" } @@ -22562,6 +22417,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-3.2.0.tgz", "integrity": "sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==", + "license": "MIT", "dependencies": { "sort-keys": "^2.0.0", "write-json-file": "^2.2.0" @@ -22574,6 +22430,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "license": "MIT", "dependencies": { "pify": "^3.0.0" }, @@ -22585,6 +22442,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", "engines": { "node": ">=4" } @@ -22593,6 +22451,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz", "integrity": "sha512-84+F0igFp2dPD6UpAQjOUX3CdKUOqUzn6oE9sDBNzUXINR5VceJ1rauZltqQB/bcYsx3EpKys4C7/PivKUAiWQ==", + "license": "MIT", "dependencies": { "detect-indent": "^5.0.0", "graceful-fs": "^4.1.2", @@ -22609,6 +22468,7 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -22898,36 +22758,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/z-schema": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", - "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", - "dev": true, - "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "bin": { - "z-schema": "bin/z-schema" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^9.4.1" - } - }, - "node_modules/z-schema/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "optional": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, "node_modules/zod": { "version": "3.23.8", "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", @@ -22937,11 +22767,12 @@ } }, "node_modules/zod-validation-error": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-1.5.0.tgz", - "integrity": "sha512-/7eFkAI4qV0tcxMBB/3+d2c1P6jzzZYdYSlBuAklzMuCrJu5bzJfHS0yVAS87dRHVlhftd6RFJDIvv03JgkSbw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz", + "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", + "license": "MIT", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "peerDependencies": { "zod": "^3.18.0" @@ -22979,8 +22810,8 @@ "version": "1.0.0", "license": "AGPL-3.0-or-later", "dependencies": { - "nextra": "^3.0.0-alpha.24", - "nextra-theme-docs": "^3.0.0-alpha.24", + "nextra": "^3.0.1", + "nextra-theme-docs": "^3.0.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, @@ -23011,16 +22842,13 @@ "idb-keyval": "^6.2.1", "json-stringify-deterministic": "^1.0.12", "lorem-ipsum": "^2.0.8", - "math-expressions": "^2.0.0-alpha66", "nanoid": "^4.0.2", "prismjs": "^1.29.0", - "react-copy-to-clipboard": "^5.0.3", + "react-copy-to-clipboard": "^5.1.0", "react-icons": "^4.12.0", "react-mathquill": "^1.0.3", "react-measure": "^2.5.2", - "react-router": "^6.23.1", - "react-router-dom": "^6.23.1", - "react-simple-code-editor": "^0.13.1", + "react-router": "^6.26.2", "react-visibility-sensor-v2": "^1.0.0", "recoil": "^0.7.7", "styled-components": "^5.3.11" diff --git a/package.json b/package.json index ab0ed2f9f..cec2e923c 100644 --- a/package.json +++ b/package.json @@ -35,56 +35,56 @@ }, "homepage": "https://github.com/Doenet/DoenetML/README.md", "devDependencies": { - "@ariakit/react": "^0.4.7", + "@ariakit/react": "^0.4.11", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@esbuild-plugins/node-modules-polyfill": "^0.2.2", "@qualified/lsp-connection": "^0.3.0", "@qualified/vscode-jsonrpc-ww": "^0.3.0", - "@rollup/pluginutils": "^5.1.0", + "@rollup/pluginutils": "^5.1.2", "@types/esprima": "^4.0.6", - "@types/react": "^18.3.3", + "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", "@uiw/react-codemirror": "^4.22.2", "@vitejs/plugin-react": "^4.3.1", - "@vitest/web-worker": "^1.6.0", - "@vscode/test-web": "^0.0.54", - "autoprefixer": "^10.4.19", + "@vitest/web-worker": "^2.1.1", + "@vscode/test-web": "^0.0.60", + "autoprefixer": "^10.4.20", "chalk": "^5.3.0", "classnames": "^2.5.1", - "compress-json": "^3.0.5", - "cypress": "^12.13.0", - "cypress-parallel": "^0.13.0", + "compress-json": "^3.1.0", + "cypress": "^13.15.0", + "cypress-parallel": "^0.14.0", "cypress-plugin-tab": "^1.0.5", - "cypress-wait-until": "^1.7.2", - "eslint": "^8.57.0", - "eslint-plugin-react": "^7.34.2", + "cypress-wait-until": "^3.0.2", + "eslint": "^8.57.1", + "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.7", + "eslint-plugin-react-refresh": "^0.4.12", "esprima": "^4.0.1", - "glob": "^10.4.1", - "jsdom": "^24.1.0", - "katex": "^0.16.10", + "glob": "^10.4.5", + "jsdom": "^24.1.3", + "katex": "^0.16.11", "micromark": "^4.0.0", - "nextra": "^3.0.0-alpha.24", - "nextra-theme-docs": "^3.0.0-alpha.24", - "node-stdlib-browser": "^1.2.0", - "postcss": "^8.4.38", - "prettier": "^3.3.2", + "nextra": "^3.0.1", + "nextra-theme-docs": "^3.0.1", + "node-stdlib-browser": "^1.2.1", + "postcss": "^8.4.47", + "prettier": "^3.3.3", "rollup-plugin-polyfill-node": "^0.13.0", "rollup-plugin-visualizer": "^5.12.0", - "tailwindcss": "^3.4.4", + "tailwindcss": "^3.4.13", "ts-morph": "^22.0.0", - "typescript": "^5.4.5", - "vite": "^5.3.0", - "vite-node": "^1.6.0", + "typescript": "^5.6.2", + "vite": "^5.4.8", + "vite-node": "^2.1.1", "vite-plugin-compile-time": "^0.2.1", - "vite-plugin-dts": "^3.9.1", - "vite-plugin-static-copy": "^1.0.5", - "vitest": "^1.6.0", - "vscode-jsonrpc": "8.2.0", + "vite-plugin-dts": "^4.2.2", + "vite-plugin-static-copy": "^1.0.6", + "vitest": "^2.1.1", + "vscode-jsonrpc": "8.2.1", "vscode-languageserver": "^9.0.1", "vscode-languageserver-protocol": "^3.17.5", - "wireit": "^0.14.4" + "wireit": "^0.14.9" }, "overrides": { "@qualified/lsp-connection": { @@ -99,5 +99,9 @@ }, "prettier": { "tabWidth": 4 + }, + "dependencies": { + "math-expressions": "^2.0.0-alpha68", + "react-router-dom": "^6.26.2" } } diff --git a/packages/docs-nextra/package.json b/packages/docs-nextra/package.json index b45fd4c44..5ed39c494 100644 --- a/packages/docs-nextra/package.json +++ b/packages/docs-nextra/package.json @@ -53,8 +53,8 @@ } }, "dependencies": { - "nextra": "^3.0.0-alpha.24", - "nextra-theme-docs": "^3.0.0-alpha.24", + "nextra": "^3.0.1", + "nextra-theme-docs": "^3.0.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, diff --git a/packages/doenetml-worker/package.json b/packages/doenetml-worker/package.json index 802944d5f..62dfd91db 100644 --- a/packages/doenetml-worker/package.json +++ b/packages/doenetml-worker/package.json @@ -22,7 +22,7 @@ }, "scripts": { "watch": "vite build --watch", - "test": "echo \"No tests \"", + "test": "vitest", "build": "wireit" }, "wireit": { diff --git a/packages/doenetml-worker/src/Core.js b/packages/doenetml-worker/src/Core.js index d4eb0f1fb..f0b44c84a 100644 --- a/packages/doenetml-worker/src/Core.js +++ b/packages/doenetml-worker/src/Core.js @@ -3384,7 +3384,7 @@ export default class Core { // compositeReplacementActiveRange will be used // - in renderers to determined if they should add commas // - in child dependencies, where they will be translated for matched children - // and used in some components to determine if thsoe children can be formed into a list + // and used in some components to determine if those children can be formed into a list parent.compositeReplacementActiveRange.push({ compositeName: child.componentName, target: await child.stateValues.target, diff --git a/packages/doenetml-worker/src/Dependencies.js b/packages/doenetml-worker/src/Dependencies.js index ed249b401..a0bd89e75 100644 --- a/packages/doenetml-worker/src/Dependencies.js +++ b/packages/doenetml-worker/src/Dependencies.js @@ -5062,6 +5062,35 @@ class ChildDependency extends Dependency { downstreamComponentTypes.push(child.componentType); } + if ( + this.originalDownstreamVariableNames.includes("hidden") && + this.downstreamPrimitives.find((x) => x !== null) + ) { + // We are asking for the hidden state variable and the result includes primitives. + // Since primitives don't have a hidden state variable, we instead depend on the hidden state variable + // of the composite. + + for (let compositeObj of this.compositeReplacementRange) { + downstreamComponentNames.push(compositeObj.compositeName); + downstreamComponentTypes.push( + this.dependencyHandler._components[ + compositeObj.compositeName + ].componentType, + ); + + this.addedCompositeHiddenDependency = true; + } + + if ( + this.addedCompositeHiddenDependency && + this.originalDownstreamVariableNames.length > 1 + ) { + // Added a composite hidden dependency but there are other variables that may not be on the composite. + // Make variables optional so we don't cause an unexpected error. + this.variablesOptional = true; + } + } + return { success: true, downstreamComponentNames, @@ -5075,6 +5104,28 @@ class ChildDependency extends Dependency { // TODO: do we have to adjust anything else from result // if we add primitives to result.value? + let compositeReplacementRange = this.compositeReplacementRange; + + if (this.addedCompositeHiddenDependency) { + // We added composite hidden dependencies. + // Delete them off the actual dependencies returned + // and instead add them to the compositeReplacesRange object returned. + + let nDepsAdded = compositeReplacementRange.length; + let extraDependencies = result.value.splice( + result.value.length - nDepsAdded, + nDepsAdded, + ); + + compositeReplacementRange = JSON.parse( + JSON.stringify(compositeReplacementRange), + ); + + for (let [ind, range] of compositeReplacementRange.entries()) { + range.hidden = extraDependencies[ind].stateValues.hidden; + } + } + let resultValueWithPrimitives = []; let resultInd = 0; @@ -5088,7 +5139,7 @@ class ChildDependency extends Dependency { } resultValueWithPrimitives.compositeReplacementRange = - this.compositeReplacementRange; + compositeReplacementRange; result.value = resultValueWithPrimitives; diff --git a/packages/doenetml-worker/src/components/Answer.js b/packages/doenetml-worker/src/components/Answer.js index aae64877a..e6a458301 100644 --- a/packages/doenetml-worker/src/components/Answer.js +++ b/packages/doenetml-worker/src/components/Answer.js @@ -1595,6 +1595,13 @@ export default class Answer extends InlineComponent { awardCredits.reduce((a, c) => a + c, 0), ); } + + // remove any trailing null's in awardsUsed + let lastNull = awardsUsed.indexOf(null); + if (lastNull !== -1) { + awardsUsed = awardsUsed.slice(0, lastNull); + } + return { setValue: { creditAchievedIfSubmit: creditAchieved, @@ -2071,6 +2078,11 @@ export default class Answer extends InlineComponent { return; } + let disabled = await this.stateValues.disabled; + if (disabled) { + return; + } + let creditAchieved = await this.stateValues.creditAchievedIfSubmit; if (await this.stateValues.handGraded) { creditAchieved = 0; diff --git a/packages/doenetml-worker/src/components/Caption.js b/packages/doenetml-worker/src/components/Caption.js index c7b13b4e4..21f2febc0 100644 --- a/packages/doenetml-worker/src/components/Caption.js +++ b/packages/doenetml-worker/src/components/Caption.js @@ -42,7 +42,7 @@ export default class Caption extends BlockComponent { inlineChildren: { dependencyType: "child", childGroups: ["inlinesBlocks"], - variableNames: ["text"], + variableNames: ["text", "hidden"], variablesOptional: true, }, }), diff --git a/packages/doenetml-worker/src/components/Cell.js b/packages/doenetml-worker/src/components/Cell.js index 7b7c0804c..6ca9cdaf7 100644 --- a/packages/doenetml-worker/src/components/Cell.js +++ b/packages/doenetml-worker/src/components/Cell.js @@ -278,7 +278,7 @@ export default class Cell extends BaseComponent { children: { dependencyType: "child", childGroups: ["maths", "anything"], - variableNames: ["text"], + variableNames: ["text", "hidden"], variablesOptional: true, }, prefill: { diff --git a/packages/doenetml-worker/src/components/Choice.js b/packages/doenetml-worker/src/components/Choice.js index 8edd6729a..774b8cdd9 100644 --- a/packages/doenetml-worker/src/components/Choice.js +++ b/packages/doenetml-worker/src/components/Choice.js @@ -60,7 +60,7 @@ export default class Choice extends InlineComponent { inlineChildren: { dependencyType: "child", childGroups: ["children"], - variableNames: ["text"], + variableNames: ["text", "hidden"], variablesOptional: true, }, }), diff --git a/packages/doenetml-worker/src/components/Footnote.js b/packages/doenetml-worker/src/components/Footnote.js index 6f976c5fa..c448e49b5 100644 --- a/packages/doenetml-worker/src/components/Footnote.js +++ b/packages/doenetml-worker/src/components/Footnote.js @@ -29,7 +29,7 @@ export default class Footnote extends InlineComponent { inlineChildren: { dependencyType: "child", childGroups: ["inlines"], - variableNames: ["text"], + variableNames: ["text", "hidden"], variablesOptional: true, }, }), diff --git a/packages/doenetml-worker/src/components/Label.js b/packages/doenetml-worker/src/components/Label.js index c9c6d17d4..79f9276cc 100644 --- a/packages/doenetml-worker/src/components/Label.js +++ b/packages/doenetml-worker/src/components/Label.js @@ -209,6 +209,7 @@ export default class Label extends InlineComponent { "value", "hasLatex", "renderAsMath", + "hidden", ], variablesOptional: true, }, @@ -241,6 +242,8 @@ export default class Label extends InlineComponent { ) { if (typeof comp !== "object") { return comp.toString(); + } else if (comp.stateValues.hidden) { + return ""; } else if ( typeof comp.stateValues.hasLatex === "boolean" && typeof comp.stateValues.value === "string" && diff --git a/packages/doenetml-worker/src/components/P.js b/packages/doenetml-worker/src/components/P.js index 1a81dc942..584f3ae41 100644 --- a/packages/doenetml-worker/src/components/P.js +++ b/packages/doenetml-worker/src/components/P.js @@ -41,7 +41,7 @@ export default class P extends BlockComponent { inlineChildren: { dependencyType: "child", childGroups: ["inlinesAndLists"], - variableNames: ["text"], + variableNames: ["text", "hidden"], variablesOptional: true, }, }), diff --git a/packages/doenetml-worker/src/components/Spreadsheet.js b/packages/doenetml-worker/src/components/Spreadsheet.ts similarity index 98% rename from packages/doenetml-worker/src/components/Spreadsheet.js rename to packages/doenetml-worker/src/components/Spreadsheet.ts index 3831f35c5..0ee0bd30a 100644 --- a/packages/doenetml-worker/src/components/Spreadsheet.js +++ b/packages/doenetml-worker/src/components/Spreadsheet.ts @@ -1,3 +1,10 @@ +//@ts-nocheck + +// Note: changed this .js file to a .ts file in order to prevent an error +// from HyperFormula when loading Core directly from vitest. +// No idea why this stops the error, but found this workaround via trial-and-error. +// This file has not been converted to typescript, hence the ts-nocheck line at the beginning. + import { normalizeIndex } from "../utils/table"; import { textToAst } from "../utils/math"; import BlockComponent from "./abstract/BlockComponent"; @@ -1026,23 +1033,23 @@ export default class Spreadsheet extends BlockComponent { // console.log(`array definition of evaluatedCells`) // console.log(globalDependencyValues) - let hf = HyperFormula.buildFromArray( - globalDependencyValues.cells, - { - licenseKey: "gpl-v3", - }, - ); + // let hf = HyperFormula.buildFromArray( + // globalDependencyValues.cells, + // { + // licenseKey: "gpl-v3", + // }, + // ); let allEvaluated = hf.getSheetValues(0); let evaluatedCells = {}; - for (let ind1 in allEvaluated) { - let row = allEvaluated[ind1]; - for (let ind2 in row) { - evaluatedCells[[ind1, ind2]] = row[ind2]; - } - } + // for (let ind1 in allEvaluated) { + // let row = allEvaluated[ind1]; + // for (let ind2 in row) { + // evaluatedCells[[ind1, ind2]] = row[ind2]; + // } + // } return { setValue: { evaluatedCells } }; }, diff --git a/packages/doenetml-worker/src/components/abstract/InlineRenderInlineChildren.js b/packages/doenetml-worker/src/components/abstract/InlineRenderInlineChildren.js index 17bb77fd9..7793eeefb 100644 --- a/packages/doenetml-worker/src/components/abstract/InlineRenderInlineChildren.js +++ b/packages/doenetml-worker/src/components/abstract/InlineRenderInlineChildren.js @@ -34,7 +34,7 @@ export default class InlineRenderInlineChildren extends InlineComponent { inlineChildren: { dependencyType: "child", childGroups: ["inlines"], - variableNames: ["text"], + variableNames: ["text", "hidden"], variablesOptional: true, }, }), diff --git a/packages/doenetml-worker/src/components/abstract/TextOrInline.js b/packages/doenetml-worker/src/components/abstract/TextOrInline.js index 7ee6ce8bd..b3e29ccd2 100644 --- a/packages/doenetml-worker/src/components/abstract/TextOrInline.js +++ b/packages/doenetml-worker/src/components/abstract/TextOrInline.js @@ -29,7 +29,7 @@ export default class TextOrInline extends InlineComponent { inlineChildren: { dependencyType: "child", childGroups: ["inlines"], - variableNames: ["text"], + variableNames: ["text", "hidden"], variablesOptional: true, }, }), diff --git a/packages/doenetml-worker/src/test/tagSpecific/answer.test.ts b/packages/doenetml-worker/src/test/tagSpecific/answer.test.ts new file mode 100644 index 000000000..96fd72580 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/answer.test.ts @@ -0,0 +1,5693 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputImmediateValue, + updateMathInputValue, + updateMatrixInputValue, + updateTextInputValue, +} from "../utils/actions"; +import { + getLatexToMathConverter, + normalizeLatexString, +} from "../../utils/math"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +async function test_math_answer({ + doenetML, + answers, + answerName = "/answer1", + mathInputName, +}: { + doenetML: string; + answers: { + latex: string; + credit: number; + preAction?: { + componentName: string; + value: string; + type: "math" | "text" | "boolean" | "choice"; + }; + submissionPrevented?: boolean; + overrideResponse?: any; + awardsUsed?: string[]; + }[]; + answerName?: string; + mathInputName?: string; +}) { + let fromLatexBase = getLatexToMathConverter(); + let fromLatex = (x: string) => fromLatexBase(normalizeLatexString(x)); + let currentResponse = "\uff3f"; + let submittedResponses: any[] = []; + let submittedCredit = 0; + let numSubmissions = 0; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + mathInputName = + mathInputName || + stateVariables[answerName].stateValues.inputChildren[0].componentName; + + if (!mathInputName) { + throw Error("Don't have mathInput name"); + } + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([currentResponse]); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + expect(stateVariables[mathInputName].stateValues.value.tree).eqls( + currentResponse, + ); + + for (let response of answers) { + if (response.preAction) { + if (response.preAction.type === "math") { + await updateMathInputValue({ + latex: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } else if (response.preAction.type === "text") { + await updateTextInputValue({ + text: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } else if (response.preAction.type === "boolean") { + await updateBooleanInputValue({ + boolean: response.preAction.value === "true", + componentName: response.preAction.componentName, + core, + }); + } else { + await core.requestAction({ + componentName: response.preAction.componentName, + actionName: "updateSelectedIndices", + args: { + selectedIndices: [parseInt(response.preAction.value)], + }, + event: null, + }); + } + } + + const latex = response.latex; + if (!response.submissionPrevented) { + currentResponse = + response.overrideResponse || fromLatex(latex).tree; + } + const credit = response.credit; + + // Type answer in + + await updateMathInputValue({ + latex, + componentName: mathInputName, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([currentResponse]); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[mathInputName].stateValues.value.tree).eqls( + currentResponse, + ); + if (response.awardsUsed) { + expect( + stateVariables[answerName].stateValues.awardsUsedIfSubmit, + ).eqls(response.awardsUsed); + } + + // submit + await core.requestAction({ + componentName: answerName, + actionName: "submitAnswer", + args: {}, + event: null, + }); + if (!response.submissionPrevented) { + submittedResponses = [currentResponse]; + numSubmissions++; + } + submittedCredit = credit; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + `Expected response ${currentResponse} to have credit ${submittedCredit}, got credit ${stateVariables[answerName].stateValues.creditAchieved}`, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([currentResponse]); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[mathInputName].stateValues.value.tree).eqls( + currentResponse, + ); + } +} + +async function test_text_answer({ + doenetML, + answers, + answerName = "/answer1", + textInputName, +}: { + doenetML: string; + answers: { text: string; credit: number }[]; + answerName?: string; + textInputName?: string; +}) { + let currentResponse = ""; + let submittedResponses: any[] = []; + let submittedCredit = 0; + let numSubmissions = 0; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + textInputName = + textInputName || + stateVariables[answerName].stateValues.inputChildren[0].componentName; + + if (!textInputName) { + throw Error("Don't have textInput name"); + } + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls([ + currentResponse, + ]); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[textInputName].stateValues.value).eqls( + currentResponse, + ); + + for (let response of answers) { + currentResponse = response.text; + const credit = response.credit; + + // Type answer in + + await updateTextInputValue({ + text: currentResponse, + componentName: textInputName, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls([ + currentResponse, + ]); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[textInputName].stateValues.value).eqls( + currentResponse, + ); + + // submit + await core.requestAction({ + componentName: answerName, + actionName: "submitAnswer", + args: {}, + event: null, + }); + submittedResponses = [currentResponse]; + submittedCredit = credit; + numSubmissions++; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + `Expected response ${currentResponse} to have credit ${submittedCredit}, got credit ${stateVariables[answerName].stateValues.creditAchieved}`, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls([ + currentResponse, + ]); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[textInputName].stateValues.value).eqls( + currentResponse, + ); + } +} + +async function test_boolean_answer({ + doenetML, + answers, + answerName = "/answer1", + booleanInputName, +}: { + doenetML: string; + answers: { boolean: boolean; credit: number }[]; + answerName?: string; + booleanInputName?: string; +}) { + let currentResponse = false; + let submittedResponses: any[] = []; + let submittedCredit = 0; + let numSubmissions = 0; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + booleanInputName = + booleanInputName || + stateVariables[answerName].stateValues.inputChildren[0].componentName; + + if (!booleanInputName) { + throw Error("Don't have booleanInput name"); + } + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls([ + currentResponse, + ]); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[booleanInputName].stateValues.value).eqls( + currentResponse, + ); + + for (let response of answers) { + currentResponse = response.boolean; + const credit = response.credit; + + // Type answer in + + await updateBooleanInputValue({ + boolean: currentResponse, + componentName: booleanInputName, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls([ + currentResponse, + ]); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[booleanInputName].stateValues.value).eqls( + currentResponse, + ); + + // submit + await core.requestAction({ + componentName: answerName, + actionName: "submitAnswer", + args: {}, + event: null, + }); + submittedResponses = [currentResponse]; + submittedCredit = credit; + numSubmissions++; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + `Expected response ${currentResponse} to have credit ${submittedCredit}, got credit ${stateVariables[answerName].stateValues.creditAchieved}`, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls([ + currentResponse, + ]); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[booleanInputName].stateValues.value).eqls( + currentResponse, + ); + } +} + +async function test_choice_answer({ + doenetML, + answers, + answerName = "/answer1", + choiceInputName, + indexByName = {}, + submitFirst = false, + skipInitialCheck = false, +}: { + doenetML: string; + answers: { + choices: string[]; + credit: number; + preAction?: { + componentName: string; + value: string; + recomputeIndices: boolean; + type: "math" | "text"; + }; + }[]; + answerName?: string; + choiceInputName?: string; + indexByName?: { [key: string]: number }; + submitFirst?: boolean; + skipInitialCheck?: boolean; +}) { + let submittedResponses: string[] = []; + let submittedCredit = 0; + let selectedValues: string[] = []; + let selectedIndices: number[] = []; + let numSubmissions = 0; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + choiceInputName = + choiceInputName || + stateVariables[answerName].stateValues.inputChildren[0].componentName; + + if (!choiceInputName) { + throw Error("Don't have choiceInput name"); + } + + if (Object.keys(indexByName).length === 0) { + indexByName = {}; + for (let [ind, val] of stateVariables[ + choiceInputName + ].stateValues.choiceTexts.entries()) { + indexByName[val] = ind + 1; + } + } + + // in a case where have invalid logic, got math expressions + // for current responses before submitting anything + if (!skipInitialCheck) { + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls( + selectedValues, + ); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[choiceInputName].stateValues.selectedValues).eqls( + selectedValues, + ); + expect( + stateVariables[choiceInputName].stateValues.selectedIndices, + ).eqls(selectedIndices); + } + + if (submitFirst) { + // submit no answer + await core.requestAction({ + componentName: answerName, + actionName: "submitAnswer", + args: {}, + event: null, + }); + submittedResponses = selectedValues; + submittedCredit = 0; + numSubmissions++; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + `Expected response ${selectedValues} to have credit ${submittedCredit}, got credit ${stateVariables[answerName].stateValues.creditAchieved}`, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls( + selectedValues, + ); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[choiceInputName].stateValues.selectedValues).eqls( + selectedValues, + ); + expect( + stateVariables[choiceInputName].stateValues.selectedIndices, + ).eqls(selectedIndices); + } + + for (let response of answers) { + if (response.preAction) { + if (response.preAction.type === "math") { + await updateMathInputValue({ + latex: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } else { + await updateTextInputValue({ + text: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } + + if (response.preAction.recomputeIndices) { + stateVariables = await returnAllStateVariables(core); + indexByName = {}; + for (let [ind, val] of stateVariables[ + choiceInputName + ].stateValues.choiceTexts.entries()) { + indexByName[val] = ind + 1; + } + } + } + + selectedValues = response.choices; + selectedIndices = selectedValues.map((val) => indexByName[val]); + const credit = response.credit; + + // select responses + + await core.requestAction({ + componentName: choiceInputName, + actionName: "updateSelectedIndices", + args: { selectedIndices }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls( + selectedValues, + ); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[choiceInputName].stateValues.selectedValues).eqls( + selectedValues, + ); + expect( + stateVariables[choiceInputName].stateValues.selectedIndices, + ).eqls(selectedIndices); + + // submit + await core.requestAction({ + componentName: answerName, + actionName: "submitAnswer", + args: {}, + event: null, + }); + submittedResponses = selectedValues; + submittedCredit = credit; + numSubmissions++; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + `Expected response ${selectedValues} to have credit ${submittedCredit}, got credit ${stateVariables[answerName].stateValues.creditAchieved}`, + ); + expect(stateVariables[answerName].stateValues.currentResponses).eqls( + selectedValues, + ); + expect(stateVariables[answerName].stateValues.submittedResponses).eqls( + submittedResponses, + ); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[choiceInputName].stateValues.selectedValues).eqls( + selectedValues, + ); + expect( + stateVariables[choiceInputName].stateValues.selectedIndices, + ).eqls(selectedIndices); + } +} + +async function test_matrix_answer({ + doenetML, + answers, + answerName = "/answer1", + matrixInputName, + originalEffectiveResponse, +}: { + doenetML: string; + answers: { + entries: { latex: string; rowInd: number; colInd: number }[]; + credit: number; + preAction?: { + componentName: string; + value: string; + type: "math" | "text" | "boolean"; + }; + submissionPrevented?: boolean; + overrideResponse: any; + awardsUsed?: string[]; + }[]; + answerName?: string; + matrixInputName?: string; + originalEffectiveResponse: any; +}) { + let currentResponse = originalEffectiveResponse; + let submittedResponses: any[] = []; + let submittedCredit = 0; + let numSubmissions = 0; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + matrixInputName = + matrixInputName || + stateVariables[answerName].stateValues.inputChildren[0].componentName; + + if (!matrixInputName) { + throw Error("Don't have matrixInput name"); + } + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([currentResponse]); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + expect(stateVariables[matrixInputName].stateValues.value.tree).eqls( + currentResponse, + ); + + for (let response of answers) { + if (response.preAction) { + if (response.preAction.type === "math") { + await updateMathInputValue({ + latex: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } else if (response.preAction.type === "text") { + await updateTextInputValue({ + text: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } else { + await updateBooleanInputValue({ + boolean: response.preAction.value === "true", + componentName: response.preAction.componentName, + core, + }); + } + } + + if (!response.submissionPrevented) { + currentResponse = response.overrideResponse; + } + const credit = response.credit; + + // Type answers in + + for (let entry of response.entries) { + await updateMatrixInputValue({ + latex: entry.latex, + rowInd: entry.rowInd, + colInd: entry.colInd, + componentName: matrixInputName, + stateVariables, + core, + }); + } + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([currentResponse]); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[matrixInputName].stateValues.value.tree).eqls( + currentResponse, + ); + if (response.awardsUsed) { + expect( + stateVariables[answerName].stateValues.awardsUsedIfSubmit, + ).eqls(response.awardsUsed); + } + + // submit + await core.requestAction({ + componentName: answerName, + actionName: "submitAnswer", + args: {}, + event: null, + }); + if (!response.submissionPrevented) { + submittedResponses = [currentResponse]; + numSubmissions++; + } + submittedCredit = credit; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + `Expected response ${currentResponse} to have credit ${submittedCredit}, got credit ${stateVariables[answerName].stateValues.creditAchieved}`, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([currentResponse]); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + expect(stateVariables[answerName].stateValues.numSubmissions).eq( + numSubmissions, + ); + expect(stateVariables[matrixInputName].stateValues.value.tree).eqls( + currentResponse, + ); + } +} + +async function test_action_answer({ + doenetML, + answers, + answerName = "/answer1", + originalEffectiveResponses, +}: { + doenetML: string; + answers: { + actionArgs: any; + actionName: string; + actionComponentName: string; + effectiveResponses: any[]; + credit: number; + preAction?: { + componentName: string; + value: string; + type: "math" | "text"; + }; + }[]; + answerName?: string; + originalEffectiveResponses: any[]; +}) { + let currentResponses = originalEffectiveResponses; + let submittedResponses: any[] = []; + let submittedCredit = 0; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(currentResponses); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + + for (let response of answers) { + if (response.preAction) { + if (response.preAction.type === "math") { + await updateMathInputValue({ + latex: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } else { + await updateTextInputValue({ + text: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } + } + + currentResponses = response.effectiveResponses; + const credit = response.credit; + + // do action for answer + + await core.requestAction({ + componentName: response.actionComponentName, + actionName: response.actionName, + args: response.actionArgs, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(currentResponses); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + // submit + await core.requestAction({ + componentName: answerName, + actionName: "submitAnswer", + args: {}, + event: null, + }); + submittedResponses = currentResponses; + submittedCredit = credit; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[answerName].stateValues.creditAchieved).eq( + submittedCredit, + `Expected response ${currentResponses} to have credit ${submittedCredit}, got credit ${stateVariables[answerName].stateValues.creditAchieved}`, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(currentResponses); + expect( + stateVariables[answerName].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(submittedResponses); + } +} + +async function test_answer_multiple_inputs({ + doenetML, + answers, + answerName = "/answer1", + inputs, +}: { + doenetML: string; + answers: { + values: string[]; + credit: number; + preAction?: { + componentName: string; + value: string; + type: "math" | "text"; + }; + awardsUsed?: string[]; + }[]; + answerName?: string; + inputs: { type: "math" | "text" | "boolean"; name?: string }[]; +}) { + let fromLatexBase = getLatexToMathConverter(); + let fromLatex = (x: string) => fromLatexBase(normalizeLatexString(x)); + let currentResponses = inputs.map((input) => { + if (input.type === "math") { + return "\uff3f"; + } else if (input.type === "text") { + return ""; + } else { + return false; + } + }); + let submittedResponses: any[] = []; + let submittedCredit = 0; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + let inputNames: string[] = inputs.map((input, i) => { + let name = + input.name || + stateVariables[answerName].stateValues.inputChildren[i] + .componentName; + + if (!name) { + throw Error(`Don't have name for input ${i}.`); + } + + return name; + }); + + function transformOutputValues(values: any[]) { + return values.map((val, i) => { + if (inputs[i].type === "math") { + val = val.tree; + } + return val; + }); + } + + function transformInputValues(values: any[]) { + return values.map((val, i) => { + if (inputs[i].type === "math") { + val = fromLatex(val).tree; + } else if (inputs[i].type === "boolean") { + val = val === "true"; + } + return val; + }); + } + + expect(stateVariables[answerName].stateValues.creditAchieved).closeTo( + submittedCredit, + 1e-14, + ); + expect( + stateVariables[answerName].stateValues.currentResponses.map((x, i) => + inputs[i].type === "math" ? x.tree : x, + ), + ).eqls(currentResponses); + expect( + stateVariables[answerName].stateValues.submittedResponses.map((x, i) => + inputs[i].type === "math" ? x.tree : x, + ), + ).eqls(submittedResponses); + expect( + transformOutputValues( + inputNames.map((name) => stateVariables[name].stateValues.value), + ), + ).eqls(currentResponses); + + for (let response of answers) { + if (response.preAction) { + if (response.preAction.type === "math") { + await updateMathInputValue({ + latex: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } else { + await updateTextInputValue({ + text: response.preAction.value, + componentName: response.preAction.componentName, + core, + }); + } + } + + const values = response.values; + + currentResponses = transformInputValues(values); + const credit = response.credit; + + // Type answers in + + for (let [ind, input] of inputs.entries()) { + if (input.type === "math") { + await updateMathInputValue({ + latex: values[ind], + componentName: inputNames[ind], + core, + }); + } else if (input.type === "text") { + await updateTextInputValue({ + text: values[ind], + componentName: inputNames[ind], + core, + }); + } else { + await updateBooleanInputValue({ + boolean: values[ind] === "true", + componentName: inputNames[ind], + core, + }); + } + } + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[answerName].stateValues.creditAchieved).closeTo( + submittedCredit, + 1e-14, + ); + expect( + transformOutputValues( + stateVariables[answerName].stateValues.currentResponses, + ), + ).eqls(currentResponses); + expect( + transformOutputValues( + stateVariables[answerName].stateValues.submittedResponses, + ), + ).eqls(submittedResponses); + + if (response.awardsUsed) { + expect( + stateVariables[answerName].stateValues.awardsUsedIfSubmit, + ).eqls(response.awardsUsed); + } + + // submit + await core.requestAction({ + componentName: answerName, + actionName: "submitAnswer", + args: {}, + event: null, + }); + submittedResponses = currentResponses; + submittedCredit = credit; + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[answerName].stateValues.creditAchieved).closeTo( + submittedCredit, + 1e-14, + `Expected response ${currentResponses} to have credit ${submittedCredit}, got credit ${stateVariables[answerName].stateValues.creditAchieved}`, + ); + expect( + transformOutputValues( + stateVariables[answerName].stateValues.currentResponses, + ), + ).eqls(currentResponses); + expect( + transformOutputValues( + stateVariables[answerName].stateValues.submittedResponses, + ), + ).eqls(submittedResponses); + } +} + +describe("Answer tag tests", async () => { + it("answer sugar from one string", async () => { + const doenetML = `x+y`; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer sugar from one macro", async () => { + const doenetML = ` + x+y + $xy`; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer sugar from one math", async () => { + const doenetML = ` + x+y + `; + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer sugar from macros and string", async () => { + const doenetML = ` + xy + $x+$y + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer sugar from maths and string", async () => { + const doenetML = ` + x+y + `; + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer sugar from math, macro, and string", async () => { + const doenetML = ` + y + x+$y + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer sugar from one string, set to text", async () => { + const doenetML = ` + hello there + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from one string, set to text, expanded", async () => { + const doenetML = ` + hello there + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from one macro, set to text", async () => { + const doenetML = ` + hello there + $h + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from one text", async () => { + const doenetML = ` + hello there + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from text with copySource", async () => { + const doenetML = ` + hello there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from one macro with createComponentOfType text", async () => { + const doenetML = ` + hello there + $(h{createComponentOfType="text"}) + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from macro and string, set to text", async () => { + const doenetML = ` + hello + $h there + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from text and string", async () => { + const doenetML = ` + hello there + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from macros and string, does not ignore blank string, set to text", async () => { + const doenetML = ` + hellothere + $h $t + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from macro, text, and string, does not ignore blank string", async () => { + const doenetML = ` + hello + $h there + `; + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + // test for bug where submitted response was not initially text + // when had only one copy of referring to all submitted responses + it("answer sugar from one string, set to text, copy all responses", async () => { + const doenetML = ` + hello there + Submitted responses: + `; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + let textInputName = + stateVariables["/answer1"].stateValues.inputChildren[0] + .componentName; + + await updateTextInputValue({ + text: " hello there ", + componentName: textInputName, + core, + }); + + // submit + await core.requestAction({ + componentName: "/answer1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sr1"].stateValues.value).eq(" hello there "); + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from one string, set to boolean", async () => { + const doenetML = ` + true + `; + + await test_boolean_answer({ + doenetML, + answers: [ + { boolean: true, credit: 1 }, + { boolean: false, credit: 0 }, + ], + }); + }); + + it("answer sugar from one boolean", async () => { + const doenetML = ` + true + `; + + await test_boolean_answer({ + doenetML, + answers: [ + { boolean: true, credit: 1 }, + { boolean: false, credit: 0 }, + ], + }); + }); + + it("answer sugar from macro and string, set to boolean", async () => { + const doenetML = ` + false + not $b + `; + + await test_boolean_answer({ + doenetML, + answers: [ + { boolean: true, credit: 1 }, + { boolean: false, credit: 0 }, + ], + }); + }); + + it("answer sugar from boolean and string", async () => { + const doenetML = ` + not false + `; + + await test_boolean_answer({ + doenetML, + answers: [ + { boolean: true, credit: 1 }, + { boolean: false, credit: 0 }, + ], + }); + }); + + it("warning for sugar with invalid type", async () => { + let core = await createTestCore({ + doenetML: ` +

x

+ `, + }); + + 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 answer: bad", + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(6); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(49); + + let stateVariables = await returnAllStateVariables(core); + let mathInputName = + stateVariables["/answer1"].stateValues.inputChildren[0] + .componentName; + + await updateMathInputValue({ + latex: "x", + componentName: mathInputName, + core, + }); + await core.requestAction({ + componentName: "/answer1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/answer1"].stateValues.creditAchieved).eq(1); + }); + + it("answer award with math", async () => { + const doenetML = ` + x+y + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer award with sugared string", async () => { + const doenetML = ` + x+y + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer award with sugared macro", async () => { + const doenetML = ` + x+y + $xy + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer award with sugared macros and string", async () => { + const doenetML = ` + xy + $x+$y + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer award with sugared macro, math, and string", async () => { + const doenetML = ` + x + $x+y + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer award with math, initially unresolved", async () => { + const doenetML = ` + x+y-3+$n + + + $n3{name="n2"} + $num1{name="n"} + $n2+$num2 + $n3+$num3 + $num3{name="n3"} + 1 + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("answer sugar from mathList", async () => { + const doenetML = ` + x+y z + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y, z", credit: 1 }, + { latex: "x, z", credit: 0.5 }, + { latex: "x", credit: 0 }, + { latex: "z", credit: 0.5 }, + { latex: "z, x+y", credit: 0.5 }, + { latex: "abc, x+y", credit: 0.5 }, + ], + }); + }); + + it("answer award with mathList", async () => { + const doenetML = ` + x+y z + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y, z", credit: 1 }, + { latex: "x, z", credit: 0.5 }, + { latex: "x", credit: 0 }, + { latex: "z", credit: 0.5 }, + { latex: "z, x+y", credit: 0.5 }, + { latex: "abc, x+y", credit: 0.5 }, + ], + }); + }); + + it("answer from mathList", async () => { + const doenetML = ` + + + $mi1 $mi2 = x+y z + + + `; + + await test_answer_multiple_inputs({ + doenetML, + answers: [ + { values: ["x+y", "z"], credit: 1 }, + { values: ["x", "z"], credit: 0.5 }, + { values: ["x", ""], credit: 0 }, + { values: ["z", ""], credit: 0.5 }, + { values: ["", "z"], credit: 0.5 }, + { values: ["", "x"], credit: 0 }, + { values: ["", "x+y"], credit: 0.5 }, + { values: ["x+y", ""], credit: 0.5 }, + { values: ["z", "x+y"], credit: 0.5 }, + ], + inputs: [ + { type: "math", name: "/mi1" }, + { type: "math", name: "/mi2" }, + ], + }); + }); + + it("answer sugar from numberList", async () => { + const doenetML = ` + 1 2 + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "1,2", credit: 1 }, + { latex: "31,2", credit: 0.5 }, + { latex: "31", credit: 0 }, + { latex: "1", credit: 0.5 }, + { latex: "2, 1", credit: 0.5 }, + ], + }); + }); + + it("answer award with numberList", async () => { + const doenetML = ` + 1 2 + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "1,2", credit: 1 }, + { latex: "31,2", credit: 0.5 }, + { latex: "31", credit: 0 }, + { latex: "1", credit: 0.5 }, + { latex: "2, 1", credit: 0.5 }, + ], + }); + }); + + it("answer award with text", async () => { + const doenetML = ` + hello there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer set to text, award with text", async () => { + const doenetML = ` + hello there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer set to text, award with sugared string", async () => { + const doenetML = ` + hello there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer set to text, award with sugared macro and string", async () => { + const doenetML = ` + hello + $h there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer award with text and string", async () => { + const doenetML = ` + hello there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer award with text, macro, and string, does not ignore blank string", async () => { + const doenetML = ` + hello + $h there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer award with text, initally unresolved", async () => { + const doenetML = ` + $n + + $n3{name="n2"} + $text1{name="n"} + $n2 $text2 + $n4 + $text3{name="n3"} + hello + $text4{name="n4"} + there + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "hellothere", credit: 0 }, + { text: "hello there", credit: 1 }, + ], + }); + }); + + it("answer sugar from textList", async () => { + const doenetML = ` + hello there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello , there ", credit: 1 }, + { text: "hello,then", credit: 0.5 }, + { text: "hello there", credit: 0 }, + { text: "there", credit: 0.5 }, + ], + }); + }); + + it("answer award with textList", async () => { + const doenetML = ` + hello there + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello , there ", credit: 1 }, + { text: "hello,then", credit: 0.5 }, + { text: "hello there", credit: 0 }, + { text: "there", credit: 0.5 }, + ], + }); + }); + + it("answer from textList", async () => { + const doenetML = ` + + + $ti1 $ti2= hello there + + + `; + + await test_answer_multiple_inputs({ + doenetML, + answers: [ + { values: [" hello ", " there "], credit: 1 }, + { values: ["hello", "then"], credit: 0.5 }, + { values: ["hello,there", ""], credit: 0 }, + { values: ["there", ""], credit: 0.5 }, + ], + inputs: [ + { type: "text", name: "/ti1" }, + { type: "text", name: "/ti2" }, + ], + }); + }); + + it("answer award with boolean", async () => { + const doenetML = ` + true + `; + + await test_boolean_answer({ + doenetML, + answers: [ + { boolean: true, credit: 1 }, + { boolean: false, credit: 0 }, + ], + }); + }); + + it("answer set to boolean, award with boolean", async () => { + const doenetML = ` + true + `; + + await test_boolean_answer({ + doenetML, + answers: [ + { boolean: true, credit: 1 }, + { boolean: false, credit: 0 }, + ], + }); + }); + + it("answer set to boolean, award with sugared macro and string", async () => { + const doenetML = ` + false + not $b + `; + + await test_boolean_answer({ + doenetML, + answers: [ + { boolean: true, credit: 1 }, + { boolean: false, credit: 0 }, + ], + }); + }); + + it("answer award with sugared boolean and string", async () => { + const doenetML = ` + false + not false + `; + + await test_boolean_answer({ + doenetML, + answers: [ + { boolean: true, credit: 1 }, + { boolean: false, credit: 0 }, + ], + }); + }); + + it("answer multiple shortcut awards", async () => { + const doenetML = ` + x+yx + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0.5 }, + { latex: "y", credit: 0 }, + ], + }); + }); + + it("answer multiple shortcut awards, initially unresolved", async () => { + const doenetML = ` + $rightAnswerx-3+$n + + x+y-3+$n + $n3{name="n2"} + $num1{name="n"} + $n2+$num2 + $n3+$num3 + $num3{name="n3"} + 1 + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x", credit: 0.5 }, + { latex: "y", credit: 0 }, + ], + }); + }); + + it("answer multiple text awards", async () => { + const doenetML = ` + hello therebye + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "bye", credit: 0.5 }, + { text: "y", credit: 0 }, + ], + }); + }); + + it("answer multiple awards, set to text", async () => { + const doenetML = ` + hello therebye + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "bye", credit: 0.5 }, + { text: "y", credit: 0 }, + ], + }); + }); + + it("answer multiple string awards, set to text", async () => { + const doenetML = ` + hello therebye + + `; + + await test_text_answer({ + doenetML, + answers: [ + { text: " hello there ", credit: 1 }, + { text: "bye", credit: 0.5 }, + { text: "y", credit: 0 }, + ], + }); + }); + + it("full answer tag", async () => { + const doenetML = ` + Enter values that sum to 3x: + + $mi1{isResponse}+$mi2{isResponse} = 3x + $mi1+$mi2 = 3 + + `; + + await test_answer_multiple_inputs({ + doenetML, + answers: [ + { values: ["x+y", "2x-y"], credit: 1 }, + { values: ["x", "3-x"], credit: 0.5 }, + { values: ["y", "3-x"], credit: 0 }, + ], + inputs: [ + { type: "math", name: "/mi1" }, + { type: "math", name: "/mi2" }, + ], + }); + }); + + it("full answer tag, two inputs inside answer, shorter form", async () => { + const doenetML = ` + Enter values that sum to 3x: + + + $mi1+$mi2 = 3x + $mi1+$mi2 = 3 + + `; + + await test_answer_multiple_inputs({ + doenetML, + answers: [ + { values: ["x+y", "2x-y"], credit: 1 }, + { values: ["x", "3-x"], credit: 0.5 }, + { values: ["y", "3-x"], credit: 0 }, + ], + inputs: [{ type: "math" }, { type: "math" }], + }); + }); + + it("full answer tag, copied in awards, shorter form", async () => { + const doenetML = ` + + $mi1+$mi2 = 3x + $mi1+$mi2 = 3 + +Enter values that sum to 3x: + + + + + + `; + + await test_answer_multiple_inputs({ + doenetML, + answers: [ + { values: ["x+y", "2x-y"], credit: 1 }, + { values: ["x", "3-x"], credit: 0.5 }, + { values: ["y", "3-x"], credit: 0 }, + ], + inputs: [ + { type: "math", name: "/mi1" }, + { type: "math", name: "/mi2" }, + ], + }); + }); + + it("full answer tag, text inputs", async () => { + const doenetML = ` + >Enter rain and snow in either order: + + $ti1{isResponse} $ti2{isResponse} = rain snow + $ti1 $ti2 = snow rain + $ti1 = rain + $ti1 = snow + $ti2 = rain + $ti2 = snow + + `; + + await test_answer_multiple_inputs({ + doenetML, + answers: [ + { values: ["rain", "snow"], credit: 1 }, + { values: ["rain", "rain"], credit: 0.5 }, + { values: ["snow", "rain"], credit: 1 }, + { values: ["snow", "snow"], credit: 0.5 }, + { values: ["fog", "hail"], credit: 0 }, + ], + inputs: [ + { type: "text", name: "/ti1" }, + { type: "text", name: "/ti2" }, + ], + }); + }); + + it("answer inequalities", async () => { + const doenetML = ` +Enter enter number larger than 5 or less than 2: + + + $m > 5 + $m < 2 + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "6", credit: 1 }, + { latex: "5", credit: 0 }, + { latex: "-3", credit: 1 }, + { latex: "5xy-5xy+9", credit: 1 }, + ], + }); + }); + + it("answer extended inequalities", async () => { + // Number between -1 and 1, inclusive + let doenetML = ` + + + -1 <= $m <= 1 + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "1", credit: 1 }, + { latex: "-1", credit: 1 }, + { latex: "0.5", credit: 1 }, + { latex: "1.1", credit: 0 }, + { latex: "-2", credit: 0 }, + { latex: "x-x", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + + // Number between -1 and 1, exclusive + doenetML = ` + + + -1 < $m < 1 + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "1", credit: 0 }, + { latex: "-1", credit: 0 }, + { latex: "0.5", credit: 1 }, + { latex: "0.99", credit: 1 }, + { latex: "-2", credit: 0 }, + { latex: "x-x", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + + // Number between -1 and 1, as greater than + doenetML = ` + + + 1 > $m >= -1 + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "1", credit: 0 }, + { latex: "-1", credit: 1 }, + { latex: "0.5", credit: 1 }, + { latex: "0.99", credit: 1 }, + { latex: "-2", credit: 0 }, + { latex: "x-x", credit: 1 }, + { latex: "x", credit: 0 }, + ], + }); + }); + + it("compound logic", async () => { + const doenetML = ` +Enter enter number larger than 5 or less than 2: + + + + + (($mi1{isResponse} = x + and $mi2{isResponse} != $mi1) + or + ($mi1 = y + and $mi2 != z + and $mi2 != q)) + and $mi3{isResponse} > 5 + + + `; + + await test_answer_multiple_inputs({ + doenetML, + answers: [ + { values: ["x", "z", "6"], credit: 1 }, + { values: ["x", "x", "6"], credit: 0 }, + { values: ["x", "z", "5"], credit: 0 }, + { values: ["y", "y", "7"], credit: 1 }, + { values: ["y", "z", "7"], credit: 0 }, + { values: ["y", "q", "7"], credit: 0 }, + { values: ["y", "y^2", "7"], credit: 1 }, + { values: ["y", "y", "a"], credit: 0 }, + ], + inputs: [ + { type: "math", name: "/mi1" }, + { type: "math", name: "/mi2" }, + { type: "math", name: "/mi3" }, + ], + }); + }); + + it("answer inside map", async () => { + const doenetML = ` + + + + + `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x", credit: 1 }, + { latex: "u", credit: 0 }, + ], + answerName: "/a/answer1", + }); + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x^2", credit: 1 }, + { latex: "v", credit: 0 }, + ], + answerName: "/b/answer1", + }); + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x^3", credit: 1 }, + { latex: "w", credit: 0 }, + ], + answerName: "/c/answer1", + }); + }); + + it("answer with shuffled choiceInput", async () => { + const doenetML = ` +The animal is a + + cat + dog + monkey + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["cat"], credit: 0.5 }, + ], + }); + }); + + it("answer with shuffled sugared choices", async () => { + const doenetML = ` +The animal is a + cat + dog + monkey + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["cat"], credit: 0.5 }, + ], + }); + }); + + it("answer with choiceInput, fixed order", async () => { + const doenetML = ` +The animal is a + + cat + dog + monkey + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["cat"], credit: 0.5 }, + ], + indexByName: { + cat: 1, + dog: 2, + monkey: 3, + }, + }); + }); + + it("answer with sugared choices, fixed order", async () => { + const doenetML = ` +The animal is a + cat + dog + monkey + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["cat"], credit: 0.5 }, + ], + indexByName: { + cat: 1, + dog: 2, + monkey: 3, + }, + }); + }); + + it("answer with select-multiple choiceInput, fixed order", async () => { + const doenetML = ` +The animal is a + + cat + dog + monkey + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 0 }, + { choices: ["dog", "cat"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["monkey", "cat", "dog"], credit: 0 }, + { choices: ["monkey", "dog"], credit: 0 }, + ], + indexByName: { + cat: 1, + dog: 2, + monkey: 3, + }, + }); + }); + + it("answer with select-multiple choiceInput, fixed order, match partial", async () => { + const doenetML = ` +The animal is a + + cat + dog + monkey + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 0.5 }, + { choices: ["dog", "cat"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["monkey", "cat", "dog"], credit: 2 / 3 }, + { choices: ["monkey", "dog"], credit: 1 / 3 }, + ], + indexByName: { + cat: 1, + dog: 2, + monkey: 3, + }, + }); + }); + + it("answer with select-multiple sugared choices, fixed order", async () => { + const doenetML = ` +The animal is a + cat + dog + monkey + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 0.5 }, + { choices: ["dog", "cat"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["monkey", "cat", "dog"], credit: 2 / 3 }, + { choices: ["monkey", "dog"], credit: 1 / 3 }, + ], + indexByName: { + cat: 1, + dog: 2, + monkey: 3, + }, + }); + }); + + it("answer with select-multiple choiceInput, fixed order, match partial in answer", async () => { + const doenetML = ` +The animal is a + + cat + dog + monkey + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 0.5 }, + { choices: ["dog", "cat"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["monkey", "cat", "dog"], credit: 2 / 3 }, + { choices: ["monkey", "dog"], credit: 1 / 3 }, + ], + indexByName: { + cat: 1, + dog: 2, + monkey: 3, + }, + }); + }); + + it("answer with choiceInput, no bug when submit first", async () => { + const doenetML = ` +The animal is a + + cat + dog + monkey + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + { choices: ["cat"], credit: 0.5 }, + ], + indexByName: { + cat: 1, + dog: 2, + monkey: 3, + }, + submitFirst: true, + }); + }); + + it("answer with variable number of choices", async () => { + const doenetML = ` +

Num:

+ + + + + + + + + + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["Get 1"], credit: 1 }, + { choices: ["Get 0"], credit: 0 }, + { choices: ["Get 0.5"], credit: 0.5 }, + { + choices: ["Get 1"], + credit: 1, + preAction: { + componentName: "/num", + value: "4", + recomputeIndices: true, + type: "math", + }, + }, + { choices: ["Get 0"], credit: 0 }, + { choices: ["Get 0.333"], credit: 1 / 3 }, + { choices: ["Get 0.667"], credit: 2 / 3 }, + { + choices: ["Get 1"], + credit: 1, + preAction: { + componentName: "/num", + value: "3", + recomputeIndices: true, + type: "math", + }, + }, + { choices: ["Get 0"], credit: 0 }, + { choices: ["Get 0.5"], credit: 0.5 }, + { + choices: ["Get 1"], + credit: 1, + preAction: { + componentName: "/num", + value: "6", + recomputeIndices: true, + type: "math", + }, + }, + { choices: ["Get 0"], credit: 0 }, + { choices: ["Get 0.2"], credit: 0.2 }, + { choices: ["Get 0.4"], credit: 0.4 }, + { choices: ["Get 0.6"], credit: 0.6 }, + { choices: ["Get 0.8"], credit: 0.8 }, + ], + }); + }); + + it("answer with user-defined choice and credit", async () => { + const doenetML = ` +

Credit for cat:

+

Last option:

+ + + cat + dog + monkey + $last.value + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 1 }, + { choices: ["cat"], credit: 0.3 }, + { + choices: ["dog"], + credit: 1, + preAction: { + componentName: "/catCredit", + value: "0.4", + recomputeIndices: true, + type: "math", + }, + }, + { choices: ["bird"], credit: 0 }, + { + choices: ["cat"], + credit: 0.4, + preAction: { + componentName: "/last", + value: "mouse", + recomputeIndices: true, + type: "text", + }, + }, + { choices: ["mouse"], credit: 0 }, + { + choices: ["cat"], + credit: 0.2, + preAction: { + componentName: "/catCredit", + value: "0.2", + recomputeIndices: true, + type: "math", + }, + }, + { choices: ["monkey"], credit: 0 }, + { + choices: ["rabbit"], + credit: 0, + preAction: { + componentName: "/last", + value: "rabbit", + recomputeIndices: true, + type: "text", + }, + }, + ], + }); + }); + + it("answer, any letter", async () => { + const doenetML = ` +Enter any letter: + + + + $userx_input elementof {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z} + + + + `; + + await test_math_answer({ + doenetML, + answerName: "/userx", + answers: [ + { latex: "a", credit: 1 }, + { latex: "c,d", credit: 0 }, + { latex: "q", credit: 1 }, + { latex: "1", credit: 0 }, + { latex: "R", credit: 1 }, + ], + }); + }); + + it("answer element of user defined set", async () => { + const doenetML = ` +

Enter a set

+

Enter an element of that set: + + + + $element elementof $set.value + + +

+ `; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "2", credit: 1 }, + { latex: "c", credit: 0 }, + { + latex: "c", + credit: 1, + preAction: { + componentName: "/set", + value: "\\{a,b,c,d,e,f,g\\}", + type: "math", + }, + }, + { latex: "g", credit: 1 }, + { latex: "2", credit: 0 }, + { + latex: "2", + credit: 0, + preAction: { + componentName: "/set", + value: "\\{(x+y)/2, e^{x^2+y}, (1,2,3) \\}", + type: "math", + }, + }, + { latex: "(1,2,3)", credit: 1 }, + { latex: "e^{x^2+y}", credit: 1 }, + { latex: "e^{x^2}", credit: 0 }, + { latex: "x+2y-x/2-3y/2", credit: 1 }, + ], + }); + }); + + it("answer based on math and text", async () => { + const doenetML = ` +

Enter a number larger than one

+

Say hello:

+ + + + $mi > 1 + and + $ti = hello + + + + `; + + await test_answer_multiple_inputs({ + doenetML, + answerName: "/a", + answers: [ + { values: ["2", ""], credit: 0.5 }, + { values: ["2", "hello"], credit: 1 }, + { values: ["0", "hello"], credit: 0.5 }, + { values: ["0", "bye"], credit: 0 }, + ], + inputs: [ + { type: "math", name: "/mi" }, + { type: "text", name: "/ti" }, + ], + }); + }); + + it("answer based on math and text, match partial in answer", async () => { + const doenetML = ` +

Enter a number larger than one

+

Say hello:

+ + + + $mi > 1 + and + $ti = hello + + + + `; + + await test_answer_multiple_inputs({ + doenetML, + answerName: "/a", + answers: [ + { values: ["2", ""], credit: 0.5 }, + { values: ["2", "hello"], credit: 1 }, + { values: ["0", "hello"], credit: 0.5 }, + { values: ["0", "bye"], credit: 0 }, + ], + inputs: [ + { type: "math", name: "/mi" }, + { type: "text", name: "/ti" }, + ], + }); + }); + + it("answer based on point", async () => { + const doenetML = ` +

Criterion:

+

Move point so that its x-coordinate is larger than $mi.value.

+ + + (0,0) + + + + + $mi < $P.x{isResponse} + + + + `; + + await test_action_answer({ + doenetML, + answerName: "/a", + originalEffectiveResponses: [0], + answers: [ + { + actionArgs: { x: 3, y: -3 }, + actionName: "movePoint", + actionComponentName: "/P", + effectiveResponses: [3], + credit: 1, + }, + { + preAction: { + type: "math", + componentName: "/mi", + value: "4", + }, + actionArgs: { x: 3, y: -3 }, + actionName: "movePoint", + actionComponentName: "/P", + effectiveResponses: [3], + credit: 0, + }, + { + actionArgs: { x: 8, y: 9 }, + actionName: "movePoint", + actionComponentName: "/P", + effectiveResponses: [8], + credit: 1, + }, + ], + }); + }); + + it("answer with unicode", async () => { + const doenetML = `x+2pi+3gamma+4mu+5xi+6eta`; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x+2\\pi+3\\gamma+4\\mu+5\\xi+6\\eta", credit: 1 }, + { latex: "x", credit: 0 }, + { latex: "x+2Ο€+3Ξ³+4ΞΌ+5ΞΎ+6Ξ·", credit: 1 }, + ], + }); + }); + + it("mark sources as responses", async () => { + const doenetML = ` +

Enter minimum:

+

Enter value larger than $min:

+ + + $val > $min + `; + + await test_math_answer({ + doenetML, + mathInputName: "/val", + answerName: "/a", + answers: [ + { + latex: "", + credit: 0, + preAction: { + componentName: "/min", + value: "2", + type: "math", + }, + }, + { latex: "3", credit: 1 }, + { latex: "2", credit: 0 }, + { + latex: "2", + credit: 1, + preAction: { + componentName: "/min", + value: "1.9", + type: "math", + }, + }, + ], + }); + }); + + it("consider as responses", async () => { + const doenetML = ` +

Enter two 2D points, where second to upward and to the right of the first: +

+ + + $P $Q + $(Q.value.x) > $(P.value.x) and $(Q.value.y) > $(P.value.y) + + + `; + + await test_answer_multiple_inputs({ + doenetML, + answerName: "/a", + answers: [ + { values: ["(2,3)", "(3,4)"], credit: 1 }, + { values: ["(5,3)", "(3,1)"], credit: 0 }, + ], + inputs: [ + { type: "math", name: "/P" }, + { type: "math", name: "/Q" }, + ], + }); + }); + + it("isResponse is not copied", async () => { + const doenetML = ` + + + + $mi{isResponse name="v"} = x + + + $v = y + + + $v = z + + `; + + await test_math_answer({ + doenetML, + mathInputName: "/mi", + answerName: "/ans", + answers: [ + { latex: "x", credit: 1 }, + { latex: "y", credit: 0.9 }, + { latex: "z", credit: 0.8 }, + ], + }); + }); + + it("isResponse from sourcesAreResponses is not copied", async () => { + const doenetML = ` + + + + $mi{name="v"} = x + + + $v = y + + + $v = z + + + `; + + await test_math_answer({ + doenetML, + mathInputName: "/mi", + answerName: "/ans", + answers: [ + { latex: "x", credit: 1 }, + { latex: "y", credit: 0.9 }, + { latex: "z", credit: 0.8 }, + ], + }); + }); + + it("isResponse from sourcesAreResponses is not recursively copied", async () => { + const doenetML = ` + + + + $mi = x + + + $m = y + + + $m.value = z + + + `; + + await test_math_answer({ + doenetML, + mathInputName: "/mi", + answerName: "/ans", + answers: [ + { latex: "x", credit: 1 }, + { latex: "y", credit: 0.9 }, + { latex: "z", credit: 0.8 }, + ], + }); + }); + + it("all composites are responses if no responses indicated", async () => { + const doenetML = ` +

Enter minimum:

+

Enter value larger than $min:

+ + + $val > $min + + `; + + await test_answer_multiple_inputs({ + doenetML, + answerName: "/a", + answers: [ + { values: ["", "2"], credit: 0 }, + { values: ["3", "2"], credit: 1 }, + ], + inputs: [ + { type: "math", name: "/val" }, + { type: "math", name: "/min" }, + ], + }); + }); + + it("choiceInput credit from boolean", async () => { + let options = ["meow", "woof", "squeak", "blub"]; + for (let ind = 1; ind <= 4; ind++) { + let core = await createTestCore({ + doenetML: ` + + + + +

What does the $animal say? + + + meow + woof + squeak + blub + + +

+ `, + requestedVariantIndex: ind, + }); + + let stateVariables = await returnAllStateVariables(core); + + let indexByName = {}; + for (let [ind, val] of stateVariables[ + "/ci" + ].stateValues.choiceTexts.entries()) { + indexByName[val] = ind + 1; + } + + for (let ind2 = 1; ind2 <= 4; ind2++) { + let selectedIndices = [indexByName[options[ind2 - 1]]]; + await core.requestAction({ + componentName: "/ci", + actionName: "updateSelectedIndices", + args: { selectedIndices }, + event: null, + }); + + await core.requestAction({ + componentName: "/ans", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + if (ind2 === ind) { + expect( + stateVariables["/ans"].stateValues.creditAchieved, + ).eq(1); + } else { + expect( + stateVariables["/ans"].stateValues.creditAchieved, + ).eq(0); + } + } + } + }); + + it("award credit from boolean", async () => { + let options = ["meow", "woof", "squeak", "blub"]; + for (let ind = 1; ind <= 4; ind++) { + let core = await createTestCore({ + doenetML: ` + + + + +

What does the $animal say? + + meow + woof + squeak + blub + +

+ `, + requestedVariantIndex: ind, + }); + + let stateVariables = await returnAllStateVariables(core); + + let textInputName = + stateVariables["/ans"].stateValues.inputChildren[0] + .componentName; + + for (let ind2 = 1; ind2 <= 4; ind2++) { + await updateTextInputValue({ + text: options[ind2 - 1], + componentName: textInputName, + core, + }); + + await core.requestAction({ + componentName: "/ans", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + if (ind2 === ind) { + expect( + stateVariables["/ans"].stateValues.creditAchieved, + ).eq(1); + } else { + expect( + stateVariables["/ans"].stateValues.creditAchieved, + ).eq(0); + } + } + } + }); + + it("number of awards credited", async () => { + const doenetML = ` +

Number of awards credited:

+

Credit for combined award:

+

Distinct numbers greater than 3: + + + + $mi1 > 3 + $mi2 > 3 + $mi1 > 3 and $mi2 > 3 and $mi1 != $mi2 + $mi1 + isnumber($mi2) + +

+ `; + + await test_answer_multiple_inputs({ + doenetML, + answerName: "/a", + answers: [ + { values: ["", ""], credit: 0, awardsUsed: [] }, + { values: ["", "1"], credit: 0, awardsUsed: ["/SecondNumber"] }, + { values: ["0", "1"], credit: 0, awardsUsed: ["/FirstNumber"] }, + { + values: ["0", "1"], + credit: 0, + preAction: { + type: "math", + componentName: "/nAwards", + value: "3", + }, + awardsUsed: ["/FirstNumber", "/SecondNumber"], + }, + { + values: ["4", "1"], + credit: 0.4, + awardsUsed: [ + "/FirstGreater3", + "/FirstNumber", + "/SecondNumber", + ], + }, + { + values: ["4", "1"], + credit: 0.4, + preAction: { + type: "math", + componentName: "/nAwards", + value: "1", + }, + awardsUsed: ["/FirstGreater3"], + }, + { + values: ["4", "4"], + credit: 0.4, + awardsUsed: ["/FirstGreater3"], + }, + { + values: ["4", "4"], + credit: 0.8, + preAction: { + type: "math", + componentName: "/nAwards", + value: "3", + }, + awardsUsed: [ + "/FirstGreater3", + "/SecondGreater3", + "/FirstNumber", + ], + }, + { + values: ["4", "5"], + credit: 1, + awardsUsed: [ + "/DistinctGreater3", + "/FirstGreater3", + "/SecondGreater3", + ], + }, + { + values: ["4", "5"], + credit: 1, + preAction: { + type: "math", + componentName: "/nAwards", + value: "1", + }, + awardsUsed: ["/DistinctGreater3"], + }, + { + values: ["4", "5"], + credit: 0.4, + preAction: { + type: "math", + componentName: "/creditForCombined", + value: "0.2", + }, + awardsUsed: ["/FirstGreater3"], + }, + { + values: ["4", "5"], + credit: 0.8, + preAction: { + type: "math", + componentName: "/nAwards", + value: "2", + }, + awardsUsed: ["/FirstGreater3", "/SecondGreater3"], + }, + { + values: ["4", "5"], + credit: 1, + preAction: { + type: "math", + componentName: "/nAwards", + value: "3", + }, + awardsUsed: [ + "/FirstGreater3", + "/SecondGreater3", + "/DistinctGreater3", + ], + }, + ], + inputs: [ + { type: "math", name: "/mi1" }, + { type: "math", name: "/mi2" }, + ], + }); + }); + + it("number of awards credited 2", async () => { + const doenetML = ` + + + + + $mi1 > 0 + $mi2 > 0 + $mi3 > 0 + $mi1 > $mi2 + $mi1 > $mi3 + $mi2 > $mi3 + $mi1 + $mi2 > 5 + $mi1 + $mi3 > 5 + $mi2 + $mi3 > 5 + $mi1 + not isnumber($mi2) + isnumber($mi3) + + `; + + await test_answer_multiple_inputs({ + doenetML, + answerName: "/a", + answers: [ + { + values: ["", "", ""], + credit: 0, + awardsUsed: [ + "/FirstShouldNumber", + "/SecondShouldNumber", + "/ThirdShouldNumber", + ], + }, + { + values: ["-5", "", ""], + credit: 0, + awardsUsed: ["/SecondShouldNumber", "/ThirdShouldNumber"], + }, + { + values: ["-5", "-5", ""], + credit: 0, + awardsUsed: ["/ThirdShouldNumber"], + }, + { values: ["-5", "-5", "-5"], credit: 0, awardsUsed: [] }, + { + values: ["-5", "-4", "-5"], + credit: 0.1, + awardsUsed: ["/SecondLargerThird"], + }, + { + values: ["-4", "-4", "-5"], + credit: 0.2, + awardsUsed: ["/FirstLargerThird", "/SecondLargerThird"], + }, + { + values: ["-3", "-4", "-5"], + credit: 0.3, + awardsUsed: [ + "/FirstLargerSecond", + "/FirstLargerThird", + "/SecondLargerThird", + ], + }, + { + values: ["8", "-4", "-5"], + credit: 0.4, + awardsUsed: [ + "/FirstPositive", + "/FirstLargerSecond", + "/FirstLargerThird", + ], + }, + { + values: ["8", "-2", "-5"], + credit: 0.65, + awardsUsed: [ + "/SumFirstSecondLarger5", + "/FirstPositive", + "/FirstLargerSecond", + ], + }, + { + values: ["8", "9", "-5"], + credit: 0.75, + awardsUsed: [ + "/SumFirstSecondLarger5", + "/FirstPositive", + "/SecondPositive", + ], + }, + { + values: ["8", "11", "-5"], + credit: 0.9, + awardsUsed: [ + "/SumFirstSecondLarger5", + "/SumSecondThirdLarger5", + "/FirstPositive", + ], + }, + { + values: ["8", "11", "-1"], + credit: 1, + awardsUsed: [ + "/SumFirstSecondLarger5", + "/SumFirstThirdLarger5", + "/SumSecondThirdLarger5", + ], + }, + { + values: ["8", "11", "6"], + credit: 1, + awardsUsed: [ + "/SumFirstSecondLarger5", + "/SumFirstThirdLarger5", + "/SumSecondThirdLarger5", + ], + }, + { + values: ["15", "11", "6"], + credit: 1, + awardsUsed: [ + "/SumFirstSecondLarger5", + "/SumFirstThirdLarger5", + "/SumSecondThirdLarger5", + ], + }, + ], + inputs: [ + { type: "math", name: "/mi1" }, + { type: "math", name: "/mi2" }, + { type: "math", name: "/mi3" }, + ], + }); + }); + + it("number of awards credited, zero credits are triggered", async () => { + const doenetML = ` + + + + + + $mi1=x and $mi2=y and $mi3=z + + + $mi1!=x and $mi2!=y and $mi3!=z + + + $mi2=x or $mi3=x + + + $mi1=y or $mi3=y + + + $mi1=z or $mi2=z + + + `; + + await test_answer_multiple_inputs({ + doenetML, + answerName: "/a", + answers: [ + { + values: ["", "", ""], + credit: 0, + awardsUsed: ["/NothingRight"], + }, + { + values: ["z", "", ""], + credit: 0, + awardsUsed: ["/NothingRight", "/zWrongSpot"], + }, + { + values: ["z", "y", ""], + credit: 1 / 3, + awardsUsed: ["/right", "/zWrongSpot"], + }, + { + values: ["z", "y", "x"], + credit: 1 / 3, + awardsUsed: ["/right", "/xWrongSpot", "/zWrongSpot"], + }, + { + values: ["y", "y", "x"], + credit: 1 / 3, + awardsUsed: ["/right", "/xWrongSpot", "/yWrongSpot"], + }, + { + values: ["y", "z", "x"], + credit: 0, + awardsUsed: ["/NothingRight", "/xWrongSpot", "/yWrongSpot"], + }, + { + values: ["y", "y", "z"], + credit: 2 / 3, + awardsUsed: ["/right", "/yWrongSpot"], + }, + { + values: ["x", "y", "z"], + credit: 1, + awardsUsed: ["/right"], + }, + ], + inputs: [ + { type: "math", name: "/mi1" }, + { type: "math", name: "/mi2" }, + { type: "math", name: "/mi3" }, + ], + }); + }); + + it("answer with choiceInput inside invalid child logic", async () => { + const doenetML = ` + + + + + 1 + 2 + 3 + 4 + 5 + + + + + + $choice1.selectedValue = 4 + + + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["4"], credit: 1 }, + { choices: ["3"], credit: 0 }, + ], + indexByName: { + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + }, + choiceInputName: "/choice1", + skipInitialCheck: true, // avoid dealing with case where start with math expressions for current responses + }); + }); + + it("maximum number of attempts", async () => { + const doenetML = `x`; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x", credit: 1 }, + { latex: "y", credit: 0 }, + { latex: "x", credit: 0, submissionPrevented: true }, + { latex: "y", credit: 0, submissionPrevented: true }, + ], + }); + + await test_math_answer({ + doenetML, + answers: [ + { latex: "y", credit: 0 }, + { latex: "x", credit: 1 }, + { latex: "y", credit: 1, submissionPrevented: true }, + { latex: "x", credit: 1, submissionPrevented: true }, + ], + }); + }); + + it("disable after correct", async () => { + const doenetML = `x`; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x", credit: 1 }, + { latex: "y", credit: 1, submissionPrevented: true }, + { latex: "x", credit: 1, submissionPrevented: true }, + { latex: "y", credit: 1, submissionPrevented: true }, + ], + }); + + await test_math_answer({ + doenetML, + answers: [ + { latex: "y", credit: 0 }, + { latex: "x", credit: 1 }, + { latex: "y", credit: 1, submissionPrevented: true }, + { latex: "x", credit: 1, submissionPrevented: true }, + ], + }); + }); + + it("award based on choice text", async () => { + const doenetML = ` + + + cat + dog + monkey + + $ci = $ca.text + + `; + + await test_choice_answer({ + doenetML, + answers: [ + { choices: ["dog"], credit: 0 }, + { choices: ["cat"], credit: 1 }, + { choices: ["monkey"], credit: 0 }, + ], + indexByName: { + cat: 1, + dog: 2, + monkey: 3, + }, + choiceInputName: "/ci", + }); + }); + + it("error expressions are not matched", async () => { + await test_math_answer({ + doenetML: `x^`, + answers: [ + { latex: "", credit: 0 }, + { latex: "x^", credit: 0 }, + { latex: "x^2", credit: 0 }, + ], + }); + + await test_math_answer({ + doenetML: `x^`, + answers: [ + { latex: "", credit: 0 }, + { latex: "x^", credit: 0 }, + { latex: "x^2", credit: 0 }, + ], + }); + }); + + it("with split symbols, specified directly on mathInput and math", async () => { + const doenetML = ` +

split symbols:

+

Answer: xyz

+ + + $ans + + `; + await test_math_answer({ + doenetML, + answers: [ + { latex: "xyz", credit: 1, overrideResponse: "xyz" }, + { + latex: "xyza", + credit: 0, + preAction: { + type: "boolean", + value: "true", + componentName: "/split", + }, + }, + { latex: "xyz", credit: 1 }, + { + latex: "xyzb", + credit: 0, + preAction: { + type: "boolean", + value: "false", + componentName: "/split", + }, + overrideResponse: "xyzb", + }, + { latex: "xyz", credit: 1, overrideResponse: "xyz" }, + ], + }); + }); + + it("with split symbols, sugared answer", async () => { + const doenetML = ` +

split symbols:

+xyz + `; + await test_math_answer({ + doenetML, + answers: [ + { latex: "xyz", credit: 1, overrideResponse: "xyz" }, + { + latex: "xyza", + credit: 0, + preAction: { + type: "boolean", + value: "true", + componentName: "/split", + }, + }, + { latex: "xyz", credit: 1 }, + { + latex: "xyzb", + credit: 0, + preAction: { + type: "boolean", + value: "false", + componentName: "/split", + }, + overrideResponse: "xyzb", + }, + { latex: "xyz", credit: 1, overrideResponse: "xyz" }, + ], + }); + }); + + it("with split symbols, shortcut award, sugared math", async () => { + const doenetML = ` +

split symbols:

+ + xyz + + `; + await test_math_answer({ + doenetML, + answers: [ + { latex: "xyz", credit: 1, overrideResponse: "xyz" }, + { + latex: "xyza", + credit: 0, + preAction: { + type: "boolean", + value: "true", + componentName: "/split", + }, + }, + { latex: "xyz", credit: 1 }, + { + latex: "xyzb", + credit: 0, + preAction: { + type: "boolean", + value: "false", + componentName: "/split", + }, + overrideResponse: "xyzb", + }, + { latex: "xyz", credit: 1, overrideResponse: "xyz" }, + ], + }); + }); + + it("with split symbols, explicit mathInput and math, but inferred split symbols", async () => { + const doenetML = ` +

split symbols:

+ + + xyz + + `; + await test_math_answer({ + doenetML, + answers: [ + { latex: "xyz", credit: 1, overrideResponse: "xyz" }, + { + latex: "xyza", + credit: 0, + preAction: { + type: "boolean", + value: "true", + componentName: "/split", + }, + }, + { latex: "xyz", credit: 1 }, + { + latex: "xyzb", + credit: 0, + preAction: { + type: "boolean", + value: "false", + componentName: "/split", + }, + overrideResponse: "xyzb", + }, + { latex: "xyz", credit: 1, overrideResponse: "xyz" }, + ], + }); + }); + + it("justSubmitted with expression containing NaN", async () => { + let core = await createTestCore({ + doenetML: ` + 0/0+1 + `, + }); + + await updateMathInputValue({ latex: "x", componentName: "/mi", core }); + + // submit + await core.requestAction({ + componentName: "/a", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + }); + + it("copy justSubmitted attribute", async () => { + let core = await createTestCore({ + doenetML: ` + + + 1 + +

The answer was just submitted.

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/cond"].replacements).eqls([]); + expect(stateVariables["/ans"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans"].stateValues.creditAchieved).eq(0); + + // submit + await core.requestAction({ + componentName: "/ans", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/cond"].replacements).eqls([ + { componentName: "/just", componentType: "p" }, + ]); + expect(stateVariables["/cond"].replacementsToWithhold).eq(0); + + expect(stateVariables["/just"].stateValues.text).eq( + "The answer was just submitted.", + ); + expect(stateVariables["/ans"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans"].stateValues.creditAchieved).eq(0); + + await updateMathInputValue({ latex: "1", componentName: "/mi", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/cond"].replacementsToWithhold).eq(1); + expect(stateVariables["/ans"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans"].stateValues.creditAchieved).eq(0); + + // submit + await core.requestAction({ + componentName: "/ans", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/cond"].replacementsToWithhold).eq(0); + expect(stateVariables["/cond"].replacements).eqls([ + { componentName: "/just", componentType: "p" }, + ]); + expect(stateVariables["/just"].stateValues.text).eq( + "The answer was just submitted.", + ); + expect(stateVariables["/ans"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans"].stateValues.creditAchieved).eq(1); + + await updateMathInputImmediateValue({ + latex: "0", + componentName: "/mi", + core, + }); + await updateMathInputImmediateValue({ + latex: "1", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/cond"].replacementsToWithhold).eq(1); + expect(stateVariables["/ans"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans"].stateValues.creditAchieved).eq(1); + }); + + it("empty mathLists always equal", async () => { + let core = await createTestCore({ + doenetML: ` + + + + = + + + + + + + = + + + + + + + = + + + + + + + = + + + `, + }); + + await core.requestAction({ + componentName: "/ans1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + await core.requestAction({ + componentName: "/ans2", + actionName: "submitAnswer", + args: {}, + event: null, + }); + await core.requestAction({ + componentName: "/ans3", + actionName: "submitAnswer", + args: {}, + event: null, + }); + await core.requestAction({ + componentName: "/ans4", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/ans3"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/ans4"].stateValues.creditAchieved).eq(1); + }); + + it("cannot change submitted or changed response", async () => { + let core = await createTestCore({ + doenetML: ` + x + +

Current Response: $a.currentResponse{assignNames="cr"}

+

Submitted Response: $a.submittedResponse{assignNames="sr"}

+ +

Change current response:

+

Change submitted response:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/cr"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/sr"]).eq(undefined); + + await updateMathInputValue({ + latex: "y", + componentName: "/micr", + core, + }); + await updateMathInputValue({ + latex: "z", + componentName: "/misr", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/cr"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/sr"]).eq(undefined); + + // submit response + await updateMathInputValue({ latex: "x", componentName: "/mia", core }); + await core.requestAction({ + componentName: "/a", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/cr"].stateValues.value.tree).eq("x"); + expect(stateVariables["/sr"].stateValues.value.tree).eq("x"); + + // cannot change from mathInputs + + await updateMathInputValue({ + latex: "y", + componentName: "/micr", + core, + }); + await updateMathInputValue({ + latex: "z", + componentName: "/misr", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/cr"].stateValues.value.tree).eq("x"); + expect(stateVariables["/sr"].stateValues.value.tree).eq("x"); + }); + + it("answer award with sugared string, copy award and overwrite properties", async () => { + const doenetML = ` + + 1.1 + + + `; + + await test_math_answer({ + doenetML, + answerName: "/an", + answers: [ + { latex: "", credit: 0, awardsUsed: [] }, + { latex: "1.1", credit: 1, awardsUsed: ["/aw"] }, + { latex: "1.11", credit: 0, awardsUsed: [] }, + { latex: "1.101", credit: 0.5, awardsUsed: ["/aw2"] }, + ], + }); + }); + + it("answer award with full award, copy award and overwrite properties", async () => { + const doenetML = ` + + + $mi=1.1 + + + `; + + await test_math_answer({ + doenetML, + answerName: "/an", + answers: [ + { latex: "", credit: 0, awardsUsed: [] }, + { latex: "1.1", credit: 1, awardsUsed: ["/aw"] }, + { latex: "1.11", credit: 0, awardsUsed: [] }, + { latex: "1.101", credit: 0.5, awardsUsed: ["/aw2"] }, + ], + }); + }); + + it("answer award with full award and outside input, copy award and overwrite properties", async () => { + const doenetML = ` + + + $mi=1.1 + + + `; + + await test_math_answer({ + doenetML, + answerName: "/an", + answers: [ + { latex: "", credit: 0, awardsUsed: [] }, + { latex: "1.1", credit: 1, awardsUsed: ["/aw"] }, + { latex: "1.11", credit: 0, awardsUsed: [] }, + { latex: "1.101", credit: 0.5, awardsUsed: ["/aw2"] }, + ], + mathInputName: "/mi", + }); + }); + + it("copied answer mirrors original", async () => { + const doenetML = ` + x+y + + `; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + + let mathInput1Name = + stateVariables["/ans1"].stateValues.inputChildren[0].componentName; + + let mathInput2Name = + stateVariables["/ans2"].stateValues.inputChildren[0].componentName; + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["\uff3f"]); + expect(stateVariables["/ans1"].stateValues.submittedResponses).eqls([]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["\uff3f"]); + expect(stateVariables["/ans2"].stateValues.submittedResponses).eqls([]); + + // Type correct answer in first blank + await updateMathInputValue({ + latex: "x+y", + componentName: mathInput1Name, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans1"].stateValues.submittedResponses).eqls([]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.submittedResponses).eqls([]); + + // submit second answer + await core.requestAction({ + componentName: "/ans2", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect( + stateVariables["/ans2"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + + // type incorrect answer into second blank + await updateMathInputValue({ + latex: "x", + componentName: mathInput2Name, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans2"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + + // submit first answer + await core.requestAction({ + componentName: "/ans1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans2"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + }); + + it("copy answer with no link", async () => { + const doenetML = ` + x+y + + `; + + let core = await createTestCore({ doenetML }); + + let stateVariables = await returnAllStateVariables(core); + + let mathInput1Name = + stateVariables["/ans1"].stateValues.inputChildren[0].componentName; + + let mathInput2Name = + stateVariables["/ans2"].stateValues.inputChildren[0].componentName; + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["\uff3f"]); + expect(stateVariables["/ans1"].stateValues.submittedResponses).eqls([]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["\uff3f"]); + expect(stateVariables["/ans2"].stateValues.submittedResponses).eqls([]); + + // Type correct answer in first blank + await updateMathInputValue({ + latex: "x+y", + componentName: mathInput1Name, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans1"].stateValues.submittedResponses).eqls([]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["\uff3f"]); + expect(stateVariables["/ans2"].stateValues.submittedResponses).eqls([]); + + // submit first answer + await core.requestAction({ + componentName: "/ans1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["\uff3f"]); + expect(stateVariables["/ans2"].stateValues.submittedResponses).eqls([]); + + // type correct answer into second blank + await updateMathInputValue({ + latex: "x+y", + componentName: mathInput2Name, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.submittedResponses).eqls([]); + + // submit second answer + await core.requestAction({ + componentName: "/ans2", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect( + stateVariables["/ans2"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + + // type incorrect answer into second blank + await updateMathInputValue({ + latex: "x", + componentName: mathInput2Name, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans2"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + + // submit second answer + await core.requestAction({ + componentName: "/ans2", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans2"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + // type incorrect answer into first blank + await updateMathInputValue({ + latex: "x", + componentName: mathInput1Name, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(1); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls([["+", "x", "y"]]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans2"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + + // submit first answer + await core.requestAction({ + componentName: "/ans1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans1"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans1"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans1"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect(stateVariables["/ans2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans2"].stateValues.creditAchieved).eq(0); + expect( + stateVariables["/ans2"].stateValues.currentResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + expect( + stateVariables["/ans2"].stateValues.submittedResponses.map( + (x) => x.tree, + ), + ).eqls(["x"]); + }); + + it("credit achieved not calculated before submit", async () => { + let core = await createTestCore({ + doenetML: ` + + x^2-2x+3 + x^2-2x+3 + + + `, + }); + + function check_have_getter(stateVarObj, have_getter = true) { + expect( + Boolean( + //@ts-ignore + Object.getOwnPropertyDescriptor(stateVarObj, "value").get || + stateVarObj.immutable, + ), + ).eq(have_getter); + } + + let components = core.components || {}; + + let mathInputName = + components["/ans"].stateValues.inputChildren[0].componentName; + + expect(components["/ans"].stateValues.justSubmitted).eq(false); + expect(components["/ans"].stateValues.creditAchieved).eq(0); + expect( + (await components["/ans"].stateValues.currentResponses).map( + (x) => x.tree, + ), + ).eqls(["\uff3f"]); + expect(await components["/ans"].stateValues.submittedResponses).eqls( + [], + ); + + expect(await components["/aw1"].stateValues.creditAchieved).eq(0); + expect(await components["/aw1"].stateValues.fractionSatisfied).eq(0); + expect(await components["/aw2"].stateValues.creditAchieved).eq(0); + expect(await components["/aw2"].stateValues.fractionSatisfied).eq(0); + + //check that have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit + + check_have_getter(components["/aw1"].state.creditAchievedIfSubmit); + check_have_getter(components["/aw1"].state.fractionSatisfiedIfSubmit); + check_have_getter(components["/aw2"].state.creditAchievedIfSubmit); + check_have_getter(components["/aw2"].state.fractionSatisfiedIfSubmit); + check_have_getter(components["/ans"].state.creditAchievedIfSubmit); + + // type correct answer + await updateMathInputValue({ + latex: "x^2-2x+3", + componentName: mathInputName, + core, + }); + + expect(components["/ans"].stateValues.justSubmitted).eq(false); + expect(components["/ans"].stateValues.creditAchieved).eq(0); + expect( + (await components["/ans"].stateValues.currentResponses).map((x) => + cleanLatex(x.toLatex()), + ), + ).eqls(["x^{2}-2x+3"]); + expect(await components["/ans"].stateValues.submittedResponses).eqls( + [], + ); + expect(await components["/aw1"].stateValues.creditAchieved).eq(0); + expect(await components["/aw1"].stateValues.fractionSatisfied).eq(0); + expect(await components["/aw2"].stateValues.creditAchieved).eq(0); + expect(await components["/aw2"].stateValues.fractionSatisfied).eq(0); + + //check that still have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit + + check_have_getter(components["/aw1"].state.creditAchievedIfSubmit); + check_have_getter(components["/aw1"].state.fractionSatisfiedIfSubmit); + check_have_getter(components["/aw2"].state.creditAchievedIfSubmit); + check_have_getter(components["/aw2"].state.fractionSatisfiedIfSubmit); + check_have_getter(components["/ans"].state.creditAchievedIfSubmit); + + // submit + + await core.requestAction({ + componentName: "/ans", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + expect(components["/ans"].stateValues.justSubmitted).eq(true); + expect(components["/ans"].stateValues.creditAchieved).eq(1); + expect( + (await components["/ans"].stateValues.currentResponses).map((x) => + cleanLatex(x.toLatex()), + ), + ).eqls(["x^{2}-2x+3"]); + expect( + (await components["/ans"].stateValues.submittedResponses).map((x) => + cleanLatex(x.toLatex()), + ), + ).eqls(["x^{2}-2x+3"]); + + // check that no longer have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit + + check_have_getter( + components["/aw1"].state.creditAchievedIfSubmit, + false, + ); + check_have_getter( + components["/aw1"].state.fractionSatisfiedIfSubmit, + false, + ); + check_have_getter( + components["/aw2"].state.creditAchievedIfSubmit, + false, + ); + check_have_getter( + components["/aw2"].state.fractionSatisfiedIfSubmit, + false, + ); + check_have_getter( + components["/ans"].state.creditAchievedIfSubmit, + false, + ); + + expect(components["/aw1"].stateValues.creditAchievedIfSubmit).eq(1); + expect(components["/aw1"].stateValues.fractionSatisfiedIfSubmit).eq(1); + expect(components["/aw2"].stateValues.creditAchievedIfSubmit).eq(0.5); + expect(components["/aw2"].stateValues.fractionSatisfiedIfSubmit).eq(1); + expect(components["/ans"].stateValues.creditAchievedIfSubmit).eq(1); + + // type partially correct answer + await updateMathInputValue({ + latex: "x^2-2x-3", + componentName: mathInputName, + core, + }); + + expect(components["/ans"].stateValues.justSubmitted).eq(false); + expect(components["/ans"].stateValues.creditAchieved).eq(1); + expect( + (await components["/ans"].stateValues.currentResponses).map((x) => + cleanLatex(x.toLatex()), + ), + ).eqls(["x^{2}-2x-3"]); + expect( + (await components["/ans"].stateValues.submittedResponses).map((x) => + cleanLatex(x.toLatex()), + ), + ).eqls(["x^{2}-2x+3"]); + expect(await components["/aw1"].stateValues.creditAchieved).eq(1); + expect(await components["/aw1"].stateValues.fractionSatisfied).eq(1); + expect(await components["/aw2"].stateValues.creditAchieved).eq(0.5); + expect(await components["/aw2"].stateValues.fractionSatisfied).eq(1); + + //check that still have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit + + check_have_getter(components["/aw1"].state.creditAchievedIfSubmit); + check_have_getter(components["/aw1"].state.fractionSatisfiedIfSubmit); + check_have_getter(components["/aw2"].state.creditAchievedIfSubmit); + check_have_getter(components["/aw2"].state.fractionSatisfiedIfSubmit); + check_have_getter(components["/ans"].state.creditAchievedIfSubmit); + + // submit + + await core.requestAction({ + componentName: "/ans", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + expect(components["/ans"].stateValues.justSubmitted).eq(true); + expect(components["/ans"].stateValues.creditAchieved).eq(0.5); + expect( + (await components["/ans"].stateValues.currentResponses).map((x) => + cleanLatex(x.toLatex()), + ), + ).eqls(["x^{2}-2x-3"]); + expect( + (await components["/ans"].stateValues.submittedResponses).map((x) => + cleanLatex(x.toLatex()), + ), + ).eqls(["x^{2}-2x-3"]); + + // check that no longer have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit + + check_have_getter( + components["/aw1"].state.creditAchievedIfSubmit, + false, + ); + check_have_getter( + components["/aw1"].state.fractionSatisfiedIfSubmit, + false, + ); + check_have_getter( + components["/aw2"].state.creditAchievedIfSubmit, + false, + ); + check_have_getter( + components["/aw2"].state.fractionSatisfiedIfSubmit, + false, + ); + check_have_getter( + components["/ans"].state.creditAchievedIfSubmit, + false, + ); + + expect(components["/aw1"].stateValues.creditAchievedIfSubmit).eq(0); + expect(components["/aw1"].stateValues.fractionSatisfiedIfSubmit).eq(0); + expect(components["/aw2"].stateValues.creditAchievedIfSubmit).eq(0.5); + expect(components["/aw2"].stateValues.fractionSatisfiedIfSubmit).eq(1); + expect(components["/ans"].stateValues.creditAchievedIfSubmit).eq(0.5); + }); + + it("short award and full award combined", async () => { + const doenetML = ` + + + + + + x^2 + + $P.x > 0 + + + `; + + await test_action_answer({ + doenetML, + answerName: "/a", + originalEffectiveResponses: ["\uff3f", 0], + answers: [ + { + preAction: { + type: "math", + componentName: "/mi", + value: "x^2", + }, + actionArgs: { x: 0, y: 0 }, + actionName: "movePoint", + actionComponentName: "/P", + effectiveResponses: [["^", "x", 2], 0], + credit: 0.6, + }, + { + actionArgs: { x: 2, y: -7 }, + actionName: "movePoint", + actionComponentName: "/P", + effectiveResponses: [["^", "x", 2], 2], + credit: 1, + }, + { + preAction: { + type: "math", + componentName: "/mi", + value: "y^2", + }, + actionArgs: { x: 2, y: -7 }, + actionName: "movePoint", + actionComponentName: "/P", + effectiveResponses: [["^", "y", 2], 2], + credit: 0.4, + }, + ], + }); + }); + + it("derivative works without award", async () => { + const doenetML = ` +What is the derivative of x^2? +$f + `; + await test_math_answer({ + doenetML, + answers: [ + { latex: "2x", credit: 1 }, + { latex: "2x/2", credit: 0 }, + ], + }); + }); + + it("case-insensitive match, text", async () => { + await test_math_answer({ + doenetML: `x+Y`, + answers: [ + { latex: "x+y", credit: 0 }, + { latex: "x+Y", credit: 1 }, + { latex: "X+Y", credit: 0 }, + { latex: "X", credit: 0 }, + { latex: "X+y", credit: 0 }, + ], + answerName: "/defSugar", + }); + + await test_math_answer({ + doenetML: `x+Y`, + answers: [ + { latex: "x+y", credit: 1 }, + { latex: "x+Y", credit: 1 }, + { latex: "X+Y", credit: 1 }, + { latex: "X", credit: 0 }, + { latex: "X+y", credit: 1 }, + ], + answerName: "/insSugar", + }); + + await test_math_answer({ + doenetML: ` + + x+Y + x+Y + `, + answers: [ + { latex: "x+y", credit: 0.5 }, + { latex: "x+Y", credit: 1 }, + { latex: "X+Y", credit: 0.5 }, + { latex: "X", credit: 0 }, + { latex: "X+y", credit: 0.5 }, + ], + answerName: "/shortAwards", + }); + + await test_math_answer({ + doenetML: ` + + + $mi = x+Y + $mi = x+Y + `, + answers: [ + { latex: "x+y", credit: 0.5 }, + { latex: "x+Y", credit: 1 }, + { latex: "X+Y", credit: 0.5 }, + { latex: "X", credit: 0 }, + { latex: "X+y", credit: 0.5 }, + ], + answerName: "/full", + }); + }); + + it("case-insensitive match, math", async () => { + await test_text_answer({ + doenetML: `Hello there!`, + answers: [ + { text: "hello there!", credit: 0 }, + { text: "Hello there!", credit: 1 }, + { text: "Hello There!", credit: 0 }, + { text: "Hello", credit: 0 }, + { text: "hello There!", credit: 0 }, + ], + answerName: "/defSugar", + }); + + await test_text_answer({ + doenetML: `Hello there!`, + answers: [ + { text: "hello there!", credit: 1 }, + { text: "Hello there!", credit: 1 }, + { text: "Hello There!", credit: 1 }, + { text: "Hello", credit: 0 }, + { text: "hello There!", credit: 1 }, + ], + answerName: "/insSugar", + }); + + await test_text_answer({ + doenetML: ` + + Hello there! + Hello there! + `, + answers: [ + { text: "hello there!", credit: 0.5 }, + { text: "Hello there!", credit: 1 }, + { text: "Hello There!", credit: 0.5 }, + { text: "Hello", credit: 0 }, + { text: "hello There!", credit: 0.5 }, + ], + answerName: "/shortAwards", + }); + + await test_text_answer({ + doenetML: ` + + + $ti = Hello there! + $ti = Hello there! + `, + answers: [ + { text: "hello there!", credit: 0.5 }, + { text: "Hello there!", credit: 1 }, + { text: "Hello There!", credit: 0.5 }, + { text: "Hello", credit: 0 }, + { text: "hello There!", credit: 0.5 }, + ], + answerName: "/full", + }); + }); + + it("match blanks", async () => { + await test_math_answer({ + doenetML: `_6^14C`, + answers: [ + { latex: "C_6^{14}", credit: 0 }, + { latex: "_6^{14}C", credit: 0 }, + ], + answerName: "/defSugar", + }); + + await test_math_answer({ + doenetML: `_6^14C`, + answers: [ + { latex: "C_6^{14}", credit: 0 }, + { latex: "_6^{14}C", credit: 1 }, + ], + answerName: "/blankSugar", + }); + + await test_math_answer({ + doenetML: `_6^14C`, + answers: [ + { latex: "C_6^{14}", credit: 0 }, + { latex: "_6^{14}C", credit: 0 }, + ], + answerName: "/defShort", + }); + + await test_math_answer({ + doenetML: `_6^14C`, + answers: [ + { latex: "C_6^{14}", credit: 0 }, + { latex: "_6^{14}C", credit: 1 }, + ], + answerName: "/blankShort", + }); + + await test_math_answer({ + doenetML: ` + + + $mi = _6^14C + `, + answers: [ + { latex: "C_6^{14}", credit: 0 }, + { latex: "_6^{14}C", credit: 0 }, + ], + answerName: "/defFull", + }); + + await test_math_answer({ + doenetML: ` + + + $mi = _6^14C + `, + answers: [ + { latex: "C_6^{14}", credit: 0 }, + { latex: "_6^{14}C", credit: 1 }, + ], + answerName: "/blankFull", + }); + }); + + it("submitted responses from copy source", async () => { + let core = await createTestCore({ + doenetML: ` + +

x + + +

+

hello + + +

+

true + + +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/xsr"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/xcr"].stateValues.value.tree).eq("\uff3f"); + + await updateMathInputValue({ latex: "x", componentName: "/mi", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/xsr"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/xcr"].stateValues.value.tree).eq("x"); + + await core.requestAction({ + componentName: "/x", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/xsr"].stateValues.value.tree).eq("x"); + expect(stateVariables["/xcr"].stateValues.value.tree).eq("x"); + + expect(stateVariables["/hellosr"].stateValues.value).eq(""); + expect(stateVariables["/hellocr"].stateValues.value).eq(""); + + await updateTextInputValue({ + text: "hello", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/hellosr"].stateValues.value).eq(""); + expect(stateVariables["/hellocr"].stateValues.value).eq("hello"); + + await core.requestAction({ + componentName: "/hello", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/hellosr"].stateValues.value).eq("hello"); + expect(stateVariables["/hellocr"].stateValues.value).eq("hello"); + + expect(stateVariables["/bsr"].stateValues.value).eq(false); + expect(stateVariables["/bcr"].stateValues.value).eq(false); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/bsr"].stateValues.value).eq(false); + expect(stateVariables["/bcr"].stateValues.value).eq(true); + + await core.requestAction({ + componentName: "/b", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/bsr"].stateValues.value).eq(true); + expect(stateVariables["/bcr"].stateValues.value).eq(true); + }); + + it("parse scientific notation", async () => { + await test_math_answer({ + doenetML: `4E3`, + answers: [ + { latex: "4E3", credit: 1 }, + { latex: "4000", credit: 0 }, + ], + answerName: "/ans", + }); + + await test_math_answer({ + doenetML: `4E3`, + answers: [ + { latex: "4E3", credit: 1 }, + { latex: "4000", credit: 0 }, + ], + answerName: "/ans", + }); + + await test_math_answer({ + doenetML: `4E3`, + answers: [ + { latex: "4E3", credit: 1 }, + { latex: "4000", credit: 0 }, + ], + answerName: "/ans", + }); + + await test_math_answer({ + doenetML: `4E3=$mi`, + answers: [ + { latex: "4E3", credit: 1 }, + { latex: "4000", credit: 0 }, + ], + answerName: "/ans", + }); + + await test_math_answer({ + doenetML: `4E3`, + answers: [ + { latex: "4E3", credit: 1, overrideResponse: 4000 }, + { latex: "4000", credit: 1 }, + ], + answerName: "/ans", + }); + + await test_math_answer({ + doenetML: `4E3`, + answers: [ + { latex: "4E3", credit: 1, overrideResponse: 4000 }, + { latex: "4000", credit: 1 }, + ], + answerName: "/ans", + }); + + await test_math_answer({ + doenetML: `4E3`, + answers: [ + { latex: "4E3", credit: 1, overrideResponse: 4000 }, + { latex: "4000", credit: 1 }, + ], + answerName: "/ans", + }); + + await test_math_answer({ + doenetML: `4E3=$mi`, + answers: [ + { latex: "4E3", credit: 1, overrideResponse: 4000 }, + { latex: "4000", credit: 1 }, + ], + answerName: "/ans", + }); + }); + + it("submitted response from matrixInput", async () => { + const doenetML = ` + + + a bc d + + `; + + let fromLatex = getLatexToMathConverter(); + await test_matrix_answer({ + doenetML, + answerName: "/ans", + originalEffectiveResponse: fromLatex( + "\\begin{matrix}{}&{}\\\\{}&{}\\end{matrix}", + ).tree, + answers: [ + { + entries: [{ latex: "x", rowInd: 0, colInd: 0 }], + credit: 0, + overrideResponse: fromLatex( + "\\begin{matrix}x&{}\\\\{}&{}\\end{matrix}", + ).tree, + }, + { + entries: [ + { latex: "y", rowInd: 0, colInd: 1 }, + { latex: "z", rowInd: 1, colInd: 0 }, + { latex: "0", rowInd: 1, colInd: 1 }, + ], + credit: 0, + overrideResponse: fromLatex( + "\\begin{matrix}x&y\\\\z&0\\end{matrix}", + ).tree, + }, + { + entries: [ + { latex: "a", rowInd: 0, colInd: 0 }, + { latex: "b", rowInd: 0, colInd: 1 }, + { latex: "c", rowInd: 1, colInd: 0 }, + { latex: "d", rowInd: 1, colInd: 1 }, + ], + credit: 1, + overrideResponse: fromLatex( + "\\begin{matrix}a&b\\\\c&d\\end{matrix}", + ).tree, + }, + ], + }); + }); + + it("a function defined by formula uses formula for a response", async () => { + const doenetML = ` +

Type the function f(x) = x^2

+

f(x) = +$userFormula +

+ + + + + $userFunction{isResponse} = $correctFunction + +`; + + await test_math_answer({ + doenetML, + answers: [ + { latex: "x^2", credit: 1 }, + { latex: "3x^2", credit: 0 }, + ], + mathInputName: "/userFormula", + }); + }); + + it("hand-graded answers", async () => { + await test_math_answer({ + doenetML: ``, + answers: [ + { latex: "x", credit: 0 }, + { latex: "y", credit: 0 }, + ], + answerName: "/a", + }); + await test_math_answer({ + doenetML: ``, + answers: [ + { latex: "x", credit: 0 }, + { latex: "y", credit: 0 }, + ], + answerName: "/a", + }); + await test_math_answer({ + doenetML: ``, + answers: [ + { latex: "x", credit: 0 }, + { latex: "y", credit: 0 }, + ], + answerName: "/a", + }); + await test_math_answer({ + doenetML: `x`, + answers: [ + { latex: "x", credit: 0 }, + { latex: "y", credit: 0 }, + ], + answerName: "/a", + }); + await test_math_answer({ + doenetML: `x`, + answers: [ + { latex: "x", credit: 0 }, + { latex: "y", credit: 0 }, + ], + answerName: "/a", + }); + await test_math_answer({ + doenetML: `x`, + answers: [ + { latex: "x", credit: 0 }, + { latex: "y", credit: 0 }, + ], + answerName: "/a", + }); + await test_math_answer({ + doenetML: `x`, + answers: [ + { latex: "x", credit: 0 }, + { latex: "y", credit: 0 }, + ], + answerName: "/a", + }); + + await test_text_answer({ + doenetML: ``, + answers: [ + { text: "hello", credit: 0 }, + { text: "bye", credit: 0 }, + ], + answerName: "/a", + }); + await test_text_answer({ + doenetML: ``, + answers: [ + { text: "hello", credit: 0 }, + { text: "bye", credit: 0 }, + ], + answerName: "/a", + }); + await test_text_answer({ + doenetML: `hello`, + answers: [ + { text: "hello", credit: 0 }, + { text: "bye", credit: 0 }, + ], + answerName: "/a", + }); + await test_text_answer({ + doenetML: `hello`, + answers: [ + { text: "hello", credit: 0 }, + { text: "bye", credit: 0 }, + ], + answerName: "/a", + }); + + await test_answer_multiple_inputs({ + doenetML: ``, + answers: [ + { values: ["x", "a"], credit: 0 }, + { values: ["y", "b"], credit: 0 }, + ], + answerName: "/a", + inputs: [{ type: "math" }, { type: "math" }], + }); + + await test_answer_multiple_inputs({ + doenetML: ``, + answers: [ + { values: ["hello", "there"], credit: 0 }, + { values: ["bye", "now"], credit: 0 }, + ], + answerName: "/a", + inputs: [{ type: "text" }, { type: "text" }], + }); + + await test_answer_multiple_inputs({ + doenetML: ``, + answers: [ + { values: ["x", "hello"], credit: 0 }, + { values: ["y", "bye"], credit: 0 }, + ], + answerName: "/a", + inputs: [{ type: "math" }, { type: "text" }], + }); + + await test_answer_multiple_inputs({ + doenetML: `$mi1$mi2`, + answers: [ + { values: ["x", "a"], credit: 0 }, + { values: ["y", "b"], credit: 0 }, + ], + answerName: "/a", + inputs: [ + { type: "math", name: "/mi1" }, + { type: "math", name: "/mi2" }, + ], + }); + + await test_answer_multiple_inputs({ + doenetML: `$ti1$ti2`, + answers: [ + { values: ["hello", "there"], credit: 0 }, + { values: ["bye", "now"], credit: 0 }, + ], + answerName: "/a", + inputs: [ + { type: "text", name: "/ti1" }, + { type: "text", name: "/ti2" }, + ], + }); + + await test_answer_multiple_inputs({ + doenetML: `$mi$ti`, + answers: [ + { values: ["x", "hello"], credit: 0 }, + { values: ["y", "bye"], credit: 0 }, + ], + answerName: "/a", + inputs: [ + { type: "math", name: "/mi" }, + { type: "text", name: "/ti" }, + ], + }); + }); + + it("display digits for credit achieved", async () => { + const doenetML = ` +

+ + x + y + + Credit: +

+ +

+ + x + y + + Credit: +

+`; + + const core = await createTestCore({ doenetML }); + + await updateMathInputValue({ + latex: "y", + componentName: "/miDefault", + core, + }); + await updateMathInputValue({ + latex: "y", + componentName: "/miLong", + core, + }); + + await core.requestAction({ + componentName: "/default", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + await core.requestAction({ + componentName: "/long", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/default_credit"].stateValues.valueForDisplay, + ).eq(0.333); + expect(stateVariables["/long_credit"].stateValues.valueForDisplay).eq( + 0.33333333, + ); + }); + + it("display digits for responses", async () => { + const doenetML = ` +

+ + 1.23456789 + Current response: + Submitted response: + +

+ +

+ + 1.23456789 + + >Current response: + Submitted response: +

+`; + + const core = await createTestCore({ doenetML }); + + await updateMathInputValue({ + latex: "1.23456789", + componentName: "/miDefault", + core, + }); + await updateMathInputValue({ + latex: "1.23456789", + componentName: "/miShort", + core, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/default_cr"].stateValues.valueForDisplay.tree, + ).eq(1.23456789); + expect( + stateVariables["/default_sr"].stateValues.valueForDisplay.tree, + ).eq("\uff3f"); + expect(stateVariables["/short_cr"].stateValues.valueForDisplay.tree).eq( + 1.23, + ); + expect(stateVariables["/short_sr"].stateValues.valueForDisplay.tree).eq( + "\uff3f", + ); + + await core.requestAction({ + componentName: "/default", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + await core.requestAction({ + componentName: "/short", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/default_cr"].stateValues.valueForDisplay.tree, + ).eq(1.23456789); + expect( + stateVariables["/default_sr"].stateValues.valueForDisplay.tree, + ).eq(1.23456789); + expect(stateVariables["/short_cr"].stateValues.valueForDisplay.tree).eq( + 1.23, + ); + expect(stateVariables["/short_sr"].stateValues.valueForDisplay.tree).eq( + 1.23, + ); + }); + + it("display digits for responses, turn math to number", async () => { + const doenetML = ` +

+ + 1.23456789 + Current response: + Submitted response: + +

+ +

+ + 1.23456789 + + >Current response: + Submitted response: +

+`; + + const core = await createTestCore({ doenetML }); + + await updateMathInputValue({ + latex: "1.23456789", + componentName: "/miDefault", + core, + }); + await updateMathInputValue({ + latex: "1.23456789", + componentName: "/miShort", + core, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/default_cr"].stateValues.valueForDisplay).eq( + 1.23456789, + ); + expect(stateVariables["/default_sr"].stateValues.valueForDisplay).eqls( + NaN, + ); + expect(stateVariables["/short_cr"].stateValues.valueForDisplay).eq( + 1.23, + ); + expect(stateVariables["/short_sr"].stateValues.valueForDisplay).eqls( + NaN, + ); + + await core.requestAction({ + componentName: "/default", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + await core.requestAction({ + componentName: "/short", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/default_cr"].stateValues.valueForDisplay).eq( + 1.23456789, + ); + expect(stateVariables["/default_sr"].stateValues.valueForDisplay).eq( + 1.23456789, + ); + expect(stateVariables["/short_cr"].stateValues.valueForDisplay).eq( + 1.23, + ); + expect(stateVariables["/short_sr"].stateValues.valueForDisplay).eq( + 1.23, + ); + }); + + it("conditional text used as correct answer", async () => { + let core = await createTestCore({ + doenetML: ` +

Enter a slope:

+ +

If this is the slope at an equilibrium of a discrete dynamical system, the equilibrium is + + stableunstable + + $ci.selectedValue + = + + + stable + + + unstable + + + + +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let indexByName = {}; + for (let [ind, val] of stateVariables[ + "/ci" + ].stateValues.choiceTexts.entries()) { + indexByName[val] = ind + 1; + } + + async function submit_selection(name: string) { + await core.requestAction({ + componentName: "/ci", + actionName: "updateSelectedIndices", + args: { selectedIndices: [indexByName[name]] }, + event: null, + }); + await core.requestAction({ + componentName: "/a", + actionName: "submitAnswer", + args: {}, + event: null, + }); + } + + await submit_selection("stable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + await submit_selection("unstable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + + await updateMathInputValue({ latex: "3", componentName: "/m", core }); + await submit_selection("stable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + await submit_selection("unstable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(1); + + await updateMathInputValue({ + latex: "-0.8", + componentName: "/m", + core, + }); + await submit_selection("stable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(1); + await submit_selection("unstable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + + await updateMathInputValue({ latex: "1/3", componentName: "/m", core }); + await submit_selection("stable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(1); + await submit_selection("unstable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + + await updateMathInputValue({ + latex: "-7/5", + componentName: "/m", + core, + }); + await submit_selection("stable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + await submit_selection("unstable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(1); + + await updateMathInputValue({ latex: "1", componentName: "/m", core }); + await submit_selection("stable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + await submit_selection("unstable"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.creditAchieved).eq(0); + }); + + it("conditional math used as correct answer", async () => { + const doenetML = ` +

Require positivenegative.

+ +

Condition on x: + + + + $x + = + + + x > 0 + + + x < 0 + + + + +

+ `; + + await test_math_answer({ + doenetML, + answerName: "/a", + answers: [ + { latex: "x > 0", credit: 0 }, + { latex: "x < 0", credit: 0 }, + { + latex: "x < 0", + credit: 1, + preAction: { + componentName: "/c", + type: "choice", + value: "2", + }, + }, + { latex: "x > 0", credit: 0 }, + { + latex: "x > 0", + credit: 1, + preAction: { + componentName: "/c", + type: "choice", + value: "1", + }, + }, + { latex: "x < 0", credit: 0 }, + ], + }); + }); +}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/boolean.cy.js b/packages/doenetml-worker/src/test/tagSpecific/boolean.test.ts similarity index 62% rename from packages/test-cypress/cypress/e2e/tagSpecific/boolean.cy.js rename to packages/doenetml-worker/src/test/tagSpecific/boolean.test.ts index 0da12884d..741748166 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/boolean.cy.js +++ b/packages/doenetml-worker/src/test/tagSpecific/boolean.test.ts @@ -1,18 +1,18 @@ -import { cesc, cesc2 } from "@doenet/utils"; - -describe("Boolean Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("basic boolean evaluation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, + updateTextInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Boolean tag tests", async () => { + it("basic boolean evaluation", async () => { + let core = await createTestCore({ + doenetML: `

true trUe @@ -89,75 +89,54 @@ describe("Boolean Tag Tests", function () {

`, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("contain.text", "a"); - let nTrues = 37, nFalses = 31; + + let stateVariables = await returnAllStateVariables(core); for (let i = 1; i <= nTrues; i++) { - cy.get(cesc(`#\\/t${i}`)).should("have.text", "true"); + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true; } - for (let i = 1; i <= nFalses; i++) { - cy.get(cesc(`#\\/f${i}`)).should("have.text", "false"); + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false; } - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 1; i <= nTrues; i++) { - expect(stateVariables[`/t${i}`].stateValues.value).to.be.true; - } - for (let i = 1; i <= nFalses; i++) { - expect(stateVariables[`/f${i}`].stateValues.value).to.be.false; - } - }); }); - it("boolean based on math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - + it("boolean based on math", async () => { + let core = await createTestCore({ + doenetML: ` + - + $mi Hello there! `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("contain.text", "Hello there!"); + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b`].stateValues.value).to.be.false; - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_text1")).should("not.exist"); + await updateMathInputValue({ latex: "3", componentName: "/mi", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b`].stateValues.value).to.be.true; - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}2x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_text1")).should("contain.text", "Hello there!"); + await updateMathInputValue({ latex: "2x", componentName: "/mi", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b`].stateValues.value).to.be.false; - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}-x-x{enter}", { - force: true, + await updateMathInputValue({ + latex: "2x-x-x", + componentName: "/mi", + core, }); - cy.get(cesc("#\\/_text1")).should("contain.text", "Hello there!"); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b`].stateValues.value).to.be.false; }); - it("boolean based on complex numbers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` + it("boolean based on complex numbers", async () => { + let core = await createTestCore({ + doenetML: `

3+4i 3i pi+e i

isnumber(re($c))

@@ -180,86 +159,64 @@ describe("Boolean Tag Tests", function () {

abs($a) < 5

`, - }, - "*", - ); }); let nTrues = 9, nFalses = 9; + + let stateVariables = await returnAllStateVariables(core); for (let i = 1; i <= nTrues; i++) { - cy.get(cesc(`#\\/t${i}`)).should("have.text", "true"); + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true; } - for (let i = 1; i <= nFalses; i++) { - cy.get(cesc(`#\\/f${i}`)).should("have.text", "false"); + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false; } - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 1; i <= nTrues; i++) { - expect(stateVariables[`/t${i}`].stateValues.value).to.be.true; - } - for (let i = 1; i <= nFalses; i++) { - expect(stateVariables[`/f${i}`].stateValues.value).to.be.false; - } - }); }); - it("boolean from computation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` + it("boolean from computation", async () => { + let core = await createTestCore({ + doenetML: ` - mod($i,2) = 1 - abs(cos(pi*$i/2)) < 10^(-12) - (-1)^$i = 1 - floor(($i+1)/2) = ceil(($i-1)/2) + mod($i,2) = 1 + abs(cos(pi*$i/2)) < 10^(-12) + (-1)^$i = 1 + floor(($i+1)/2) = ceil(($i-1)/2) `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean2")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean3")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean4")).should("have.text", "false"); - - cy.get(cesc("#\\/i") + " textarea").type("{end}{backspace}4{enter}", { - force: true, }); - cy.get(cesc("#\\/_boolean1")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean2")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean3")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean4")).should("have.text", "true"); - cy.get(cesc("#\\/i") + " textarea").type("{end}{backspace}-7{enter}", { - force: true, - }); - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean2")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean3")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean4")).should("have.text", "false"); - - cy.get(cesc("#\\/i") + " textarea").type( - "{end}{backspace}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_boolean1")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean2")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean3")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean4")).should("have.text", "true"); + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b1`].stateValues.value).to.be.true; + expect(stateVariables[`/b2`].stateValues.value).to.be.true; + expect(stateVariables[`/b3`].stateValues.value).to.be.false; + expect(stateVariables[`/b4`].stateValues.value).to.be.false; + + await updateMathInputValue({ latex: "4", componentName: "/i", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b1`].stateValues.value).to.be.false; + expect(stateVariables[`/b2`].stateValues.value).to.be.false; + expect(stateVariables[`/b3`].stateValues.value).to.be.true; + expect(stateVariables[`/b4`].stateValues.value).to.be.true; + + await updateMathInputValue({ latex: "-7", componentName: "/i", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b1`].stateValues.value).to.be.true; + expect(stateVariables[`/b2`].stateValues.value).to.be.true; + expect(stateVariables[`/b3`].stateValues.value).to.be.false; + expect(stateVariables[`/b4`].stateValues.value).to.be.false; + + await updateMathInputValue({ latex: "0", componentName: "/i", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b1`].stateValues.value).to.be.false; + expect(stateVariables[`/b2`].stateValues.value).to.be.false; + expect(stateVariables[`/b3`].stateValues.value).to.be.true; + expect(stateVariables[`/b4`].stateValues.value).to.be.true; }); - it("boolean with lists", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` + it("boolean with lists", async () => { + let core = await createTestCore({ + doenetML: ` 1,2 = 1 2 1,2 = 2 1 1,2 = 2 1 @@ -303,55 +260,21 @@ describe("Boolean Tag Tests", function () { a, b = b a `, - }, - "*", - ); }); - cy.get(cesc("#\\/t1")).should("have.text", "true"); - cy.get(cesc("#\\/t2")).should("have.text", "true"); - cy.get(cesc("#\\/t3")).should("have.text", "true"); - cy.get(cesc("#\\/t4")).should("have.text", "true"); - cy.get(cesc("#\\/t5")).should("have.text", "true"); - cy.get(cesc("#\\/t6")).should("have.text", "true"); - cy.get(cesc("#\\/t7")).should("have.text", "true"); - cy.get(cesc("#\\/t8")).should("have.text", "true"); - cy.get(cesc("#\\/t9")).should("have.text", "true"); - cy.get(cesc("#\\/t10")).should("have.text", "true"); - cy.get(cesc("#\\/t11")).should("have.text", "true"); - cy.get(cesc("#\\/t12")).should("have.text", "true"); - cy.get(cesc("#\\/t13")).should("have.text", "true"); - cy.get(cesc("#\\/t14")).should("have.text", "true"); - cy.get(cesc("#\\/t15")).should("have.text", "true"); - cy.get(cesc("#\\/t16")).should("have.text", "true"); - cy.get(cesc("#\\/t17")).should("have.text", "true"); - cy.get(cesc("#\\/t18")).should("have.text", "true"); - cy.get(cesc("#\\/t19")).should("have.text", "true"); - cy.get(cesc("#\\/t20")).should("have.text", "true"); - cy.get(cesc("#\\/t21")).should("have.text", "true"); - - cy.get(cesc("#\\/f1")).should("have.text", "false"); - cy.get(cesc("#\\/f2")).should("have.text", "false"); - cy.get(cesc("#\\/f3")).should("have.text", "false"); - cy.get(cesc("#\\/f4")).should("have.text", "false"); - cy.get(cesc("#\\/f5")).should("have.text", "false"); - cy.get(cesc("#\\/f6")).should("have.text", "false"); - cy.get(cesc("#\\/f7")).should("have.text", "false"); - cy.get(cesc("#\\/f8")).should("have.text", "false"); - cy.get(cesc("#\\/f9")).should("have.text", "false"); - cy.get(cesc("#\\/f10")).should("have.text", "false"); - cy.get(cesc("#\\/f11")).should("have.text", "false"); - cy.get(cesc("#\\/f12")).should("have.text", "false"); - cy.get(cesc("#\\/f13")).should("have.text", "false"); - cy.get(cesc("#\\/f14")).should("have.text", "false"); - cy.get(cesc("#\\/f15")).should("have.text", "false"); - cy.get(cesc("#\\/f16")).should("have.text", "false"); - cy.get(cesc("#\\/f17")).should("have.text", "false"); - cy.get(cesc("#\\/f18")).should("have.text", "false"); - cy.get(cesc("#\\/f19")).should("have.text", "false"); + let nTrues = 21, + nFalses = 19; + + let stateVariables = await returnAllStateVariables(core); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true; + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false; + } }); - it("element of list, set, or string", () => { + it("element of list, set, or string", async () => { let elements = [ { element: "1", @@ -731,7 +654,7 @@ describe("Boolean Tag Tests", function () { }, ]; - let doenetML = "a"; + let doenetML = ""; for (let [ind, info] of elements.entries()) { doenetML += `\n${info.element} elementof ${info.set}`; @@ -740,42 +663,33 @@ describe("Boolean Tag Tests", function () { doenetML += `\n${info.element} notelementof ${info.set}`; } - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); + let core = await createTestCore({ + doenetML, }); - cy.get(cesc2("#/_text1")).should("contain.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, info] of elements.entries()) { - expect( - stateVariables[`/s${ind}`].stateValues.value, - `Checking if ${info.element} is element of ${info.set}`, - ).eq(info.isElement && !info.isInvalid); - expect( - stateVariables[`/n${ind}`].stateValues.value, - `Checking if ${info.element} is not element of ${info.set}`, - ).eq(!info.isElement && !info.isInvalid); - expect( - stateVariables[`/sci${ind}`].stateValues.value, - `Checking if ${info.element} is case-insensitive element of ${info.set}`, - ).eq(info.isElementCaseInsensitive && !info.isInvalid); - expect( - stateVariables[`/nsci${ind}`].stateValues.value, - `Checking if ${info.element} is not case-insensitive element of ${info.set}`, - ).eq(!info.isElementCaseInsensitive && !info.isInvalid); - } - }); + let stateVariables = await returnAllStateVariables(core); + + for (let [ind, info] of elements.entries()) { + expect( + stateVariables[`/s${ind}`].stateValues.value, + `Checking if ${info.element} is element of ${info.set}`, + ).eq(info.isElement && !info.isInvalid); + expect( + stateVariables[`/n${ind}`].stateValues.value, + `Checking if ${info.element} is not element of ${info.set}`, + ).eq(!info.isElement && !info.isInvalid); + expect( + stateVariables[`/sci${ind}`].stateValues.value, + `Checking if ${info.element} is case-insensitive element of ${info.set}`, + ).eq(info.isElementCaseInsensitive && !info.isInvalid); + expect( + stateVariables[`/nsci${ind}`].stateValues.value, + `Checking if ${info.element} is not case-insensitive element of ${info.set}`, + ).eq(!info.isElementCaseInsensitive && !info.isInvalid); + } }); - it("subset or superset of list or set", () => { + it("subset or superset of list or set", async () => { let elements = [ { set1: "x+x y-y", @@ -1027,7 +941,7 @@ describe("Boolean Tag Tests", function () { }, ]; - let doenetML = "a"; + let doenetML = ""; for (let [ind, info] of elements.entries()) { doenetML += `\n${info.set1} subset ${info.set2}`; @@ -1040,62 +954,51 @@ describe("Boolean Tag Tests", function () { doenetML += `\n${info.set1} notsuperset ${info.set2}`; } - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); + let core = await createTestCore({ + doenetML, }); - cy.get(cesc2("#/_text1")).should("contain.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, info] of elements.entries()) { - expect( - stateVariables[`/sb${ind}`].stateValues.value, - `Checking if ${info.set1} is subset of ${info.set2}`, - ).eq(info.isSubset && !info.isInvalid); - expect( - stateVariables[`/nsb${ind}`].stateValues.value, - `Checking if ${info.set1} is not subset of ${info.set2}`, - ).eq(!info.isSubset && !info.isInvalid); - expect( - stateVariables[`/sp${ind}`].stateValues.value, - `Checking if ${info.set1} is superset of ${info.set2}`, - ).eq(info.isSuperset && !info.isInvalid); - expect( - stateVariables[`/nsp${ind}`].stateValues.value, - `Checking if ${info.set1} is not superset of ${info.set2}`, - ).eq(!info.isSuperset && !info.isInvalid); - expect( - stateVariables[`/sbci${ind}`].stateValues.value, - `Checking if ${info.set1} is case-insensitive subset of ${info.set2}`, - ).eq(info.isSubsetCaseInsensitive && !info.isInvalid); - expect( - stateVariables[`/nsbci${ind}`].stateValues.value, - `Checking if ${info.set1} is not case-insensitive subset of ${info.set2}`, - ).eq(!info.isSubsetCaseInsensitive && !info.isInvalid); - expect( - stateVariables[`/spci${ind}`].stateValues.value, - `Checking if ${info.set1} is case-insensitive superset of ${info.set2}`, - ).eq(info.isSupersetCaseInsensitive && !info.isInvalid); - expect( - stateVariables[`/nspci${ind}`].stateValues.value, - `Checking if ${info.set1} is not case-insensitive superset of ${info.set2}`, - ).eq(!info.isSupersetCaseInsensitive && !info.isInvalid); - } - }); + let stateVariables = await returnAllStateVariables(core); + + for (let [ind, info] of elements.entries()) { + expect( + stateVariables[`/sb${ind}`].stateValues.value, + `Checking if ${info.set1} is subset of ${info.set2}`, + ).eq(info.isSubset && !info.isInvalid); + expect( + stateVariables[`/nsb${ind}`].stateValues.value, + `Checking if ${info.set1} is not subset of ${info.set2}`, + ).eq(!info.isSubset && !info.isInvalid); + expect( + stateVariables[`/sp${ind}`].stateValues.value, + `Checking if ${info.set1} is superset of ${info.set2}`, + ).eq(info.isSuperset && !info.isInvalid); + expect( + stateVariables[`/nsp${ind}`].stateValues.value, + `Checking if ${info.set1} is not superset of ${info.set2}`, + ).eq(!info.isSuperset && !info.isInvalid); + expect( + stateVariables[`/sbci${ind}`].stateValues.value, + `Checking if ${info.set1} is case-insensitive subset of ${info.set2}`, + ).eq(info.isSubsetCaseInsensitive && !info.isInvalid); + expect( + stateVariables[`/nsbci${ind}`].stateValues.value, + `Checking if ${info.set1} is not case-insensitive subset of ${info.set2}`, + ).eq(!info.isSubsetCaseInsensitive && !info.isInvalid); + expect( + stateVariables[`/spci${ind}`].stateValues.value, + `Checking if ${info.set1} is case-insensitive superset of ${info.set2}`, + ).eq(info.isSupersetCaseInsensitive && !info.isInvalid); + expect( + stateVariables[`/nspci${ind}`].stateValues.value, + `Checking if ${info.set1} is not case-insensitive superset of ${info.set2}`, + ).eq(!info.isSupersetCaseInsensitive && !info.isInvalid); + } }); - it("boolean with texts", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` + it("boolean with texts", async () => { + let core = await createTestCore({ + doenetML: ` hello there = hello there hello there = hello there hello there = hello there @@ -1108,79 +1011,57 @@ describe("Boolean Tag Tests", function () { hello there = hello, there hello there = hello , there - hello there = hellothere hello there = hellothere hello there = hellothere hello there = hello there hello there = hello, there - - `, - }, - "*", - ); }); - cy.get(cesc("#\\/t1")).should("have.text", "true"); - cy.get(cesc("#\\/t2")).should("have.text", "true"); - cy.get(cesc("#\\/t3")).should("have.text", "true"); - cy.get(cesc("#\\/t4")).should("have.text", "true"); - cy.get(cesc("#\\/t5")).should("have.text", "true"); - cy.get(cesc("#\\/t5")).should("have.text", "true"); - cy.get(cesc("#\\/t6")).should("have.text", "true"); - cy.get(cesc("#\\/t7")).should("have.text", "true"); - cy.get(cesc("#\\/t8")).should("have.text", "true"); - cy.get(cesc("#\\/t9")).should("have.text", "true"); - cy.get(cesc("#\\/t10")).should("have.text", "true"); - cy.get(cesc("#\\/t11")).should("have.text", "true"); - - cy.get(cesc("#\\/f1")).should("have.text", "false"); - cy.get(cesc("#\\/f2")).should("have.text", "false"); - cy.get(cesc("#\\/f3")).should("have.text", "false"); - cy.get(cesc("#\\/f4")).should("have.text", "false"); - cy.get(cesc("#\\/f5")).should("have.text", "false"); + let nTrues = 11, + nFalses = 5; + + let stateVariables = await returnAllStateVariables(core); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true; + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false; + } }); - it("math errors and invalid targets are not equal", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - = - != - / = - - / != - - - $invalid = $invalid - $invalid != $invalid - $nothing = $nada - $nothing != $nada + it("math errors and invalid targets are not equal", async () => { + let core = await createTestCore({ + doenetML: ` + + = + != + / = - + / != - + + $invalid = $invalid + $invalid != $invalid + $nothing = $nada + $nothing != $nada `, - }, - "*", - ); }); + let nTrues = 4, + nFalses = 4; - cy.get(cesc("#\\/_boolean1")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean2")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean3")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean4")).should("have.text", "true"); - - cy.get(cesc("#\\/_boolean5")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean6")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean7")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean8")).should("have.text", "true"); + let stateVariables = await returnAllStateVariables(core); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true; + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false; + } }); - it("boolean with number strings for text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("boolean with number strings for text", async () => { + let core = await createTestCore({ + doenetML: ` 1 2 @@ -1193,134 +1074,213 @@ describe("Boolean Tag Tests", function () { $c = three $c = four `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/one")).should("have.text", "false"); - cy.get(cesc("#\\/two")).should("have.text", "false"); - cy.get(cesc("#\\/three")).should("have.text", "false"); - cy.get(cesc("#\\/four")).should("have.text", "false"); - - cy.get(cesc(`#\\/c_choice1_input`)).click(); - cy.get(cesc("#\\/one")).should("have.text", "true"); - cy.get(cesc("#\\/two")).should("have.text", "false"); - cy.get(cesc("#\\/three")).should("have.text", "false"); - cy.get(cesc("#\\/four")).should("have.text", "false"); - - cy.get(cesc(`#\\/c_choice2_input`)).click(); - cy.get(cesc("#\\/one")).should("have.text", "false"); - cy.get(cesc("#\\/two")).should("have.text", "true"); - cy.get(cesc("#\\/three")).should("have.text", "false"); - cy.get(cesc("#\\/four")).should("have.text", "false"); - - cy.get(cesc(`#\\/c_choice3_input`)).click(); - cy.get(cesc("#\\/one")).should("have.text", "false"); - cy.get(cesc("#\\/two")).should("have.text", "false"); - cy.get(cesc("#\\/three")).should("have.text", "true"); - cy.get(cesc("#\\/four")).should("have.text", "false"); - - cy.get(cesc(`#\\/c_choice4_input`)).click(); - cy.get(cesc("#\\/one")).should("have.text", "false"); - cy.get(cesc("#\\/two")).should("have.text", "false"); - cy.get(cesc("#\\/three")).should("have.text", "false"); - cy.get(cesc("#\\/four")).should("have.text", "true"); + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/one`].stateValues.value).to.be.false; + expect(stateVariables[`/two`].stateValues.value).to.be.false; + expect(stateVariables[`/three`].stateValues.value).to.be.false; + expect(stateVariables[`/four`].stateValues.value).to.be.false; + + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/c", + args: { selectedIndices: [1] }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/one`].stateValues.value).to.be.true; + expect(stateVariables[`/two`].stateValues.value).to.be.false; + expect(stateVariables[`/three`].stateValues.value).to.be.false; + expect(stateVariables[`/four`].stateValues.value).to.be.false; + + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/c", + args: { selectedIndices: [2] }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/one`].stateValues.value).to.be.false; + expect(stateVariables[`/two`].stateValues.value).to.be.true; + expect(stateVariables[`/three`].stateValues.value).to.be.false; + expect(stateVariables[`/four`].stateValues.value).to.be.false; + + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/c", + args: { selectedIndices: [3] }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/one`].stateValues.value).to.be.false; + expect(stateVariables[`/two`].stateValues.value).to.be.false; + expect(stateVariables[`/three`].stateValues.value).to.be.true; + expect(stateVariables[`/four`].stateValues.value).to.be.false; + + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/c", + args: { selectedIndices: [4] }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/one`].stateValues.value).to.be.false; + expect(stateVariables[`/two`].stateValues.value).to.be.false; + expect(stateVariables[`/three`].stateValues.value).to.be.false; + expect(stateVariables[`/four`].stateValues.value).to.be.true; }); - it("boolean adapts to text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - + it("boolean adapts to text", async () => { + let core = await createTestCore({ + doenetML: ` +

You are hungry. $bi

-

Are you sure?

+

Are you sure?

`, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. false", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("false"); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. true", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("true"); + + await updateTextInputValue({ + text: "false", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. false"); - cy.get(cesc("#\\/ti_input")).should("have.value", "false"); + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. false", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("false"); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. true"); - cy.get(cesc("#\\/ti_input")).should("have.value", "true"); + await updateTextInputValue({ + text: "tRuE", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/ti_input")).clear().type("false{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. false"); - cy.get(cesc("#\\/ti_input")).should("have.value", "false"); + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. true", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("true"); - cy.get(cesc("#\\/ti_input")).clear().type("tRuE{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. true"); - cy.get(cesc("#\\/ti_input")).should("have.value", "true"); + await updateTextInputValue({ text: "0", componentName: "/ti", core }); + stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/ti_input")).clear().type("0{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. true"); - cy.get(cesc("#\\/ti_input")).should("have.value", "true"); + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. true", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("true"); - cy.get(cesc("#\\/ti_input")).clear().type("1=0{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. true"); - cy.get(cesc("#\\/ti_input")).should("have.value", "true"); + await updateTextInputValue({ text: "1=0", componentName: "/ti", core }); + stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/ti_input")).clear().type("f{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. true"); - cy.get(cesc("#\\/ti_input")).should("have.value", "true"); + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. true", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("true"); - cy.get(cesc("#\\/ti_input")).clear().type("FALSE{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. false"); - cy.get(cesc("#\\/ti_input")).should("have.value", "false"); + await updateTextInputValue({ text: "f", componentName: "/ti", core }); + stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/ti_input")).clear().type("1{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. false"); - cy.get(cesc("#\\/ti_input")).should("have.value", "false"); + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. true", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("true"); - cy.get(cesc("#\\/ti_input")).clear().type("t{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. false"); - cy.get(cesc("#\\/ti_input")).should("have.value", "false"); + await updateTextInputValue({ + text: "FALSE", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. true"); - cy.get(cesc("#\\/ti_input")).should("have.value", "true"); + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. false", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("false"); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/t")).should("have.text", "You are hungry. false"); - cy.get(cesc("#\\/ti_input")).should("have.value", "false"); + await updateTextInputValue({ text: "1", componentName: "/ti", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. false", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("false"); + + await updateTextInputValue({ text: "t", componentName: "/ti", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. false", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("false"); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. true", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("true"); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/t`].stateValues.value).eq( + "You are hungry. false", + ); + expect(stateVariables[`/ti`].stateValues.value).eq("false"); }); - it("boolean does not adapt while number adapts", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("boolean does not adapt while number adapts", async () => { + let core = await createTestCore({ + doenetML: ` 3 != 1 and true 3 != 1 and true and 4 = 4 `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/b1")).should("have.text", "true"); - cy.get(cesc("#\\/b2")).should("have.text", "true"); + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b1`].stateValues.value).to.be.true; + expect(stateVariables[`/b2`].stateValues.value).to.be.true; }); - it("overwrite properties when copying", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("overwrite properties when copying", async () => { + let core = await createTestCore({ + doenetML: ` x+x = 2x $b{symbolicEquality name="b1"} @@ -1331,28 +1291,21 @@ describe("Boolean Tag Tests", function () { $b4{simplifyOnCompare="false" name="b5"} $b5{simplifyOnCompare="true" name="b6"} `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/b1")).should("have.text", "false"); - cy.get(cesc("#\\/b2")).should("have.text", "true"); - cy.get(cesc("#\\/b3")).should("have.text", "false"); - cy.get(cesc("#\\/b4")).should("have.text", "true"); - cy.get(cesc("#\\/b5")).should("have.text", "false"); - cy.get(cesc("#\\/b6")).should("have.text", "true"); + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b`].stateValues.value).to.be.true; + expect(stateVariables[`/b1`].stateValues.value).to.be.false; + expect(stateVariables[`/b2`].stateValues.value).to.be.true; + expect(stateVariables[`/b3`].stateValues.value).to.be.false; + expect(stateVariables[`/b4`].stateValues.value).to.be.true; + expect(stateVariables[`/b5`].stateValues.value).to.be.false; + expect(stateVariables[`/b6`].stateValues.value).to.be.true; }); - it("boolean simplifyOnCompare bug", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("verify fix of boolean simplifyOnCompare bug", async () => { + let core = await createTestCore({ + doenetML: ` -5e^(-t) = -5e^(-t) @@ -1360,23 +1313,16 @@ describe("Boolean Tag Tests", function () { -5e^(-t) = $orig.value{simplify} `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/b1")).should("have.text", "true"); - cy.get(cesc("#\\/b2")).should("have.text", "true"); + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b1`].stateValues.value).to.be.true; + expect(stateVariables[`/b2`].stateValues.value).to.be.true; }); - it("case insensitive match", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("case insensitive match", async () => { + let core = await createTestCore({ + doenetML: ` a/B = A/b a/B = A/b a/B = A/b @@ -1384,27 +1330,20 @@ describe("Boolean Tag Tests", function () { one Word = One word one Word = One word `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/b1")).should("have.text", "false"); - cy.get(cesc("#\\/b2")).should("have.text", "true"); - cy.get(cesc("#\\/b3")).should("have.text", "false"); - cy.get(cesc("#\\/b4")).should("have.text", "true"); - cy.get(cesc("#\\/b5")).should("have.text", "false"); - cy.get(cesc("#\\/b6")).should("have.text", "true"); + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b1`].stateValues.value).to.be.false; + expect(stateVariables[`/b2`].stateValues.value).to.be.true; + expect(stateVariables[`/b3`].stateValues.value).to.be.false; + expect(stateVariables[`/b4`].stateValues.value).to.be.true; + expect(stateVariables[`/b5`].stateValues.value).to.be.false; + expect(stateVariables[`/b6`].stateValues.value).to.be.true; }); - it("match blanks", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("match blanks", async () => { + let core = await createTestCore({ + doenetML: ` /a = /a /a = /a /a = /a @@ -1414,29 +1353,22 @@ describe("Boolean Tag Tests", function () { _6^14C = _6^14C _6^14C = _6^14C `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/b1")).should("have.text", "false"); - cy.get(cesc("#\\/b2")).should("have.text", "true"); - cy.get(cesc("#\\/b3")).should("have.text", "false"); - cy.get(cesc("#\\/b4")).should("have.text", "true"); - cy.get(cesc("#\\/b5")).should("have.text", "false"); - cy.get(cesc("#\\/b6")).should("have.text", "true"); - cy.get(cesc("#\\/b7")).should("have.text", "false"); - cy.get(cesc("#\\/b8")).should("have.text", "true"); + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables[`/b1`].stateValues.value).to.be.false; + expect(stateVariables[`/b2`].stateValues.value).to.be.true; + expect(stateVariables[`/b3`].stateValues.value).to.be.false; + expect(stateVariables[`/b4`].stateValues.value).to.be.true; + expect(stateVariables[`/b5`].stateValues.value).to.be.false; + expect(stateVariables[`/b6`].stateValues.value).to.be.true; + expect(stateVariables[`/b7`].stateValues.value).to.be.false; + expect(stateVariables[`/b8`].stateValues.value).to.be.true; }); - it("boolean with symbolic functions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("boolean with symbolic functions", async () => { + let core = await createTestCore({ + doenetML: ` (f(a)-g(b))(x) = (g(b)-f(a))(-x) @@ -1462,21 +1394,17 @@ describe("Boolean Tag Tests", function () { (f^3(a)-g^2(b))(x) = (g^3(b)-f^2(a))(-x) `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load + let nTrues = 4, + nFalses = 4; - cy.get(cesc("#\\/t1")).should("have.text", "true"); - cy.get(cesc("#\\/t2")).should("have.text", "true"); - cy.get(cesc("#\\/t3")).should("have.text", "true"); - cy.get(cesc("#\\/t4")).should("have.text", "true"); - - cy.get(cesc("#\\/f1")).should("have.text", "false"); - cy.get(cesc("#\\/f2")).should("have.text", "false"); - cy.get(cesc("#\\/f3")).should("have.text", "false"); - cy.get(cesc("#\\/f4")).should("have.text", "false"); + let stateVariables = await returnAllStateVariables(core); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true; + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false; + } }); }); diff --git a/packages/doenetml-worker/src/test/tagSpecific/conditionalcontent.test.ts b/packages/doenetml-worker/src/test/tagSpecific/conditionalcontent.test.ts new file mode 100644 index 000000000..30f949e17 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/conditionalcontent.test.ts @@ -0,0 +1,1549 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, + updateTextInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Conditional content tag tests", async () => { + // tests without cases or else + + async function check_inline_sign_number(core) { + async function check_text(description: string) { + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/p"].stateValues.text + .replace(/\s+/g, " ") + .trim(), + ).eq(`You typed ${description}.`); + } + + await check_text("something else"); + + await updateMathInputValue({ latex: "10", componentName: "/n", core }); + await check_text("a positive number"); + + await updateMathInputValue({ + latex: "-5/9", + componentName: "/n", + core, + }); + await check_text("a negative number"); + + await updateMathInputValue({ latex: "5-5", componentName: "/n", core }); + await check_text("zero"); + + await updateMathInputValue({ latex: "x", componentName: "/n", core }); + await check_text("something else"); + } + + it("inline content containing sign of number", async () => { + let core = await createTestCore({ + doenetML: ` + + +

You typed + + a positive number. + + + a negative number. + + + zero. + + + something else. + +

+ `, + }); + + await check_inline_sign_number(core); + }); + + it("inline content containing sign of number, use XML entities", async () => { + let core = await createTestCore({ + doenetML: ` + + +

You typed + + a positive number. + + + a negative number. + + + zero. + + + something else. + +

+ `, + }); + + await check_inline_sign_number(core); + }); + + it("block content containing sign of number", async () => { + let core = await createTestCore({ + doenetML: ` + + +
+

You typed a positive number.

+
+
+

You typed a negative number.

+
+
+

You typed zero.

+
+
+

You typed something else.

+
+ `, + }); + + const options = [ + "a positive number", + "a negative number", + "zero", + "something else", + ]; + async function check_text(index: number) { + let stateVariables = await returnAllStateVariables(core); + + for (let i = 1; i <= 4; i++) { + expect(stateVariables[`/section${i}`].activeChildren.length).eq( + i === index ? 3 : 0, + ); + } + + let p = + stateVariables[`/section${index}`].activeChildren[1] + .componentName; + + expect( + stateVariables[p].stateValues.text.replace(/\s+/g, " ").trim(), + ).eq(`You typed ${options[index - 1]}.`); + } + + await check_text(4); + + await updateMathInputValue({ latex: "10", componentName: "/n", core }); + await check_text(1); + + await updateMathInputValue({ + latex: "-5/9", + componentName: "/n", + core, + }); + await check_text(2); + + await updateMathInputValue({ latex: "5-5", componentName: "/n", core }); + await check_text(3); + + await updateMathInputValue({ latex: "x", componentName: "/n", core }); + await check_text(4); + }); + + it("include blank string between tags", async () => { + let core = await createTestCore({ + doenetML: ` + + foxjumps + + + + + +

The $animal $verb.

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq(""); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq("The fox jumps."); + }); + + it("assignNames gives blanks for strings but strings still displayed", async () => { + let core = await createTestCore({ + doenetML: ` + +

+ dog mouse cat +

+ +

$a

+ +

$b

+ +

$c

+ +

+ +

$d

+ +

$e

+ +

$f

+ + `, + }); + + async function check_text(names: string[]) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).contain( + names.join(" "), + ); + expect(stateVariables["/pa"].stateValues.text).eq(names[0] || ""); + expect(stateVariables["/pb"].stateValues.text).eq(""); + expect(stateVariables["/pc"].stateValues.text).eq(names[2] || ""); + expect(stateVariables["/p2"].stateValues.text).contain( + names.join(" "), + ); + expect(stateVariables["/pd"].stateValues.text).eq(names[0] || ""); + expect(stateVariables["/pe"].stateValues.text).eq(""); + expect(stateVariables["/pf"].stateValues.text).eq(names[2] || ""); + } + + await check_text([]); + + // enter 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_text(["dog", "mouse", "cat"]); + + // enter 0 + await updateMathInputValue({ latex: "0", componentName: "/n", core }); + await check_text([]); + }); + + it("correctly withhold replacements when shadowing", async () => { + let core = await createTestCore({ + doenetML: ` +

Hide greeting: + +

+ +

Greeting is hidden: $hide. Greeting: Hello!

+ +

Show copy: + +

+ + $p + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq( + "Greeting is hidden: false. Greeting: Hello!", + ); + + expect(stateVariables["/p2"]).eq(undefined); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/hide", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq( + "Greeting is hidden: true. Greeting: ", + ); + + expect(stateVariables["/p2"]).eq(undefined); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/show_copy", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p2"].stateValues.text).eq( + "Greeting is hidden: true. Greeting: ", + ); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/hide", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq( + "Greeting is hidden: false. Greeting: Hello!", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "Greeting is hidden: false. Greeting: Hello!", + ); + }); + + // tests with cases or else + + it("case/else with single text, assign sub on copy", async () => { + let core = await createTestCore({ + doenetML: ` + +

a: + dog + cat + mouse +

+ +

a1: $a{assignNames="a1"}

+ +

b: $cc{assignNames="(b)"}

+ +

b1: $b{name="b1"}

+ + `, + }); + + async function check_text(name: string) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pa"].stateValues.text).eq(`a: ${name}`); + expect(stateVariables["/pa1"].stateValues.text).eq(`a1: ${name}`); + expect(stateVariables["/pb"].stateValues.text).eq(`b: ${name}`); + expect(stateVariables["/pb1"].stateValues.text).eq(`b1: ${name}`); + + expect(stateVariables["/a1"].stateValues.text).eq(`${name}`); + expect(stateVariables["/b"].stateValues.text).eq(`${name}`); + expect(stateVariables["/b1"].stateValues.text).eq(`${name}`); + } + + // enter 1 + + await updateMathInputValue({ componentName: "/n", latex: "1", core }); + await check_text("cat"); + + // enter 10 + + await updateMathInputValue({ componentName: "/n", latex: "10", core }); + await check_text("mouse"); + + // enter -1 + + await updateMathInputValue({ componentName: "/n", latex: "-1", core }); + await check_text("dog"); + + // enter x + + await updateMathInputValue({ componentName: "/n", latex: "x", core }); + await check_text("mouse"); + }); + + it("case/else with single text, initially assign sub", async () => { + let core = await createTestCore({ + doenetML: ` + +

a: + dog + cat + mouse +

+ +

a1: $a{name="a1"}

+ +

b: $cc{assignNames="b"}

+ +

b1: $b{assignNames="b1"}

+ + `, + }); + + async function check_text(name: string) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pa"].stateValues.text).eq(`a: ${name}`); + expect(stateVariables["/pa1"].stateValues.text).eq(`a1: ${name}`); + expect(stateVariables["/pb"].stateValues.text).eq(`b: ${name}`); + expect(stateVariables["/pb1"].stateValues.text).eq(`b1: ${name}`); + + expect(stateVariables["/a"].stateValues.text).eq(`${name}`); + expect(stateVariables["/a1"].stateValues.text).eq(`${name}`); + expect(stateVariables["/b1"].stateValues.text).eq(`${name}`); + } + + // enter 1 + + await updateMathInputValue({ componentName: "/n", latex: "1", core }); + await check_text("cat"); + + // enter 10 + + await updateMathInputValue({ componentName: "/n", latex: "10", core }); + await check_text("mouse"); + + // enter -1 + + await updateMathInputValue({ componentName: "/n", latex: "-1", core }); + await check_text("dog"); + + // enter x + + await updateMathInputValue({ componentName: "/n", latex: "x", core }); + await check_text("mouse"); + }); + + async function check_test_math_optional(core, namespaces = ["", "", ""]) { + async function check_items(text: string, math: any, optional?: string) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`${namespaces[0]}/a`].stateValues.text).eq( + text, + ); + expect(stateVariables[`/a1`].stateValues.text).eq(text); + expect(stateVariables[`${namespaces[1]}/e`].stateValues.text).eq( + text, + ); + expect(stateVariables[`/e1`].stateValues.text).eq(text); + expect(stateVariables[`${namespaces[2]}/j`].stateValues.text).eq( + text, + ); + expect(stateVariables[`/j1`].stateValues.text).eq(text); + + expect( + stateVariables[`${namespaces[0]}/b`].stateValues.value.tree, + ).eqls(math); + expect(stateVariables[`/b1`].stateValues.value.tree).eqls(math); + expect( + stateVariables[`${namespaces[1]}/f`].stateValues.value.tree, + ).eqls(math); + expect(stateVariables[`/f1`].stateValues.value.tree).eqls(math); + expect( + stateVariables[`${namespaces[2]}/k`].stateValues.value.tree, + ).eqls(math); + expect(stateVariables[`/k1`].stateValues.value.tree).eqls(math); + + if (optional) { + expect( + stateVariables[`${namespaces[0]}/c`].stateValues.text, + ).eq(optional); + expect(stateVariables[`/c1`].stateValues.text).eq(optional); + expect( + stateVariables[`${namespaces[1]}/g`].stateValues.text, + ).eq(optional); + expect(stateVariables[`/g1`].stateValues.text).eq(optional); + expect( + stateVariables[`${namespaces[2]}/l`].stateValues.text, + ).eq(optional); + expect(stateVariables[`/l1`].stateValues.text).eq(optional); + } else { + expect(stateVariables[`${namespaces[0]}/c`] === undefined).eq( + true, + ); + expect(stateVariables[`/c1`] === undefined).eq(true); + expect(stateVariables[`${namespaces[1]}/g`] === undefined).eq( + true, + ); + expect(stateVariables[`/g1`] === undefined).eq(true); + expect(stateVariables[`${namespaces[2]}/l`] === undefined).eq( + true, + ); + expect(stateVariables[`/l1`] === undefined).eq(true); + } + + expect(stateVariables[`${namespaces[0]}/d`]).eq(undefined); + expect(stateVariables[`/d1`]).eq(undefined); + expect(stateVariables[`${namespaces[1]}/h`]).eq(undefined); + expect(stateVariables[`/h1`]).eq(undefined); + expect(stateVariables[`${namespaces[2]}/i`]).eq(undefined); + expect(stateVariables[`/i1`]).eq(undefined); + } + + await check_items("mouse", "z"); + + // enter 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items("cat", "y"); + + // enter 10 + await updateMathInputValue({ latex: "10", componentName: "/n", core }); + await check_items("mouse", "z"); + + // enter -1 + await updateMathInputValue({ latex: "-1", componentName: "/n", core }); + await check_items("dog", "x", "optional text!"); + + // enter x + await updateMathInputValue({ latex: "x", componentName: "/n", core }); + await check_items("mouse", "z"); + } + + it("case/else with text, math, and optional", async () => { + let core = await createTestCore({ + doenetML: ` + +

original: + dog x + optional text! + + cat y + + mouse z + +

+ +

a1: $a{name="a1"}

+

b1: $b{name="b1"}

+

c1: $c{name="c1"}

+

d1: $d{name="d1"}

+ +

copy:

+ +

e1: $e{name="e1"}

+

f1: $f{name="f1"}

+

g1: $g{name="g1"}

+

h1: $h{name="h1"}

+

i1: $i{name="i1"}

+ +

copied copy:

+ +

j1: $j{name="j1"}

+

k1: $k{name="k1"}

+

l1: $l{name="l1"}

+ `, + }); + + await check_test_math_optional(core); + }); + + it("case/else with text, math, and optional, new namespace", async () => { + let core = await createTestCore({ + doenetML: ` + +

original: + dog x + optional text! + + cat y + + mouse z + +

+ +

a1: $(s1/a{name="a1"})

+

b1: $(s1/b{name="b1"})

+

c1: $(s1/c{name="c1"})

+

d1: $(s1/d{name="d1"})

+ +

copy:

+ +

e1: $(s2/e{name="e1"})

+

f1: $(s2/f{name="f1"})

+

g1: $(s2/g{name="g1"})

+

h1: $(s2/h{name="h1"})

+

i1: $(s2/i{name="i1"})

+ +

copied copy:

+ +

j1: $(s3/j{name="j1"})

+

k1: $(s3/k{name="k1"})

+

l1: $(s3/l{name="l1"})

+ `, + }); + + await check_test_math_optional(core, ["/s1", "/s2", "/s3"]); + }); + + async function check_internal_external({ + core, + namePrefixes, + skipSingletons = false, + calcNegativeFromContainers, + }: { + core: any; + namePrefixes: string[]; + skipSingletons?: boolean; + calcNegativeFromContainers?: string[]; + }) { + async function check_items({ + animal, + plant, + num, + x, + a, + calcFromContainers, + }: { + animal: string; + plant: string; + num: number; + x: any; + a: any; + calcFromContainers?: string[]; + }) { + const p = ["*", num, a, x]; + + let stateVariables = await returnAllStateVariables(core); + + if (calcFromContainers) { + // special case where didn't add a namespace and didn't name sub-components. + // We can get some components from the containers, + // and the other components just were not created + + // first none of the regular items exist + for (let item of [ + `${namePrefixes[0]}animal`, + `${namePrefixes[0]}plant`, + `${namePrefixes[0]}p`, + `/animal`, + `/plant`, + `/p`, + `/xx`, + `/aa`, + `${namePrefixes[1]}animal`, + `${namePrefixes[1]}plant`, + `${namePrefixes[1]}p`, + `/animalCopy`, + `/plantCopy`, + `/pCopy`, + `/xxCopy`, + `/aaCopy`, + ]) { + expect(stateVariables[item]).eq(undefined); + } + + let names1 = stateVariables[ + calcFromContainers[0] + ].activeChildren + .map((x) => x.componentName) + .filter((x) => x); + + expect(stateVariables[names1[0]].stateValues.text).eq(animal); + expect(stateVariables[names1[1]].stateValues.text).eq(plant); + expect(stateVariables[names1[2]].stateValues.value.tree).eqls( + p, + ); + + let names2 = stateVariables[ + calcFromContainers[1] + ].activeChildren + .map((x) => x.componentName) + .filter((x) => x); + + expect(stateVariables[names2[0]].stateValues.text).eq(animal); + expect(stateVariables[names2[1]].stateValues.text).eq(plant); + expect(stateVariables[names2[2]].stateValues.value.tree).eqls( + p, + ); + } else { + expect( + stateVariables[`${namePrefixes[0]}animal`].stateValues.text, + ).eq(animal); + expect( + stateVariables[`${namePrefixes[0]}plant`].stateValues.text, + ).eq(plant); + expect( + stateVariables[`${namePrefixes[0]}p`].stateValues.value + .tree, + ).eqls(p); + + expect(stateVariables[`/animal`].stateValues.text).eq(animal); + expect(stateVariables[`/plant`].stateValues.text).eq(plant); + expect(stateVariables[`/p`].stateValues.value.tree).eqls(p); + + if (!skipSingletons) { + expect(stateVariables[`/xx`].stateValues.value.tree).eqls( + x, + ); + expect(stateVariables[`/aa`].stateValues.value.tree).eqls( + a, + ); + } + + expect( + stateVariables[`${namePrefixes[1]}animal`].stateValues.text, + ).eq(animal); + expect( + stateVariables[`${namePrefixes[1]}plant`].stateValues.text, + ).eq(plant); + expect( + stateVariables[`${namePrefixes[1]}p`].stateValues.value + .tree, + ).eqls(p); + + expect(stateVariables[`/animalCopy`].stateValues.text).eq( + animal, + ); + expect(stateVariables[`/plantCopy`].stateValues.text).eq(plant); + expect(stateVariables[`/pCopy`].stateValues.value.tree).eqls(p); + + if (!skipSingletons) { + expect( + stateVariables[`/xxCopy`].stateValues.value.tree, + ).eqls(x); + expect( + stateVariables[`/aaCopy`].stateValues.value.tree, + ).eqls(a); + } + } + } + + await check_items({ + animal: "mouse", + plant: "bush", + num: 6, + x: "z", + a: "c", + }); + + // enter 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + + await check_items({ + animal: "cat", + plant: "shrub", + num: 5, + x: "y", + a: "b", + }); + + // enter -1 + await updateMathInputValue({ latex: "-1", componentName: "/n", core }); + + await check_items({ + animal: "dog", + plant: "tree", + num: 4, + x: "x", + a: "a", + calcFromContainers: calcNegativeFromContainers, + }); + + // enter 10 + await updateMathInputValue({ latex: "10", componentName: "/n", core }); + + await check_items({ + animal: "mouse", + plant: "bush", + num: 6, + x: "z", + a: "c", + }); + } + + it("references to internal and external components", async () => { + let core = await createTestCore({ + doenetML: ` + dog + cat + mouse + + +

original: + + $x1 + $y1 + 3xa + $a1$b1 + + + $x2 + $y2 + 4yb + $a2$b2 + + + $x3 + $y3 + 5zc + $a3$b3 + +

+ + tree + shrub + bush + +

Selected options repeated

+ $a_animal{name="animal"} + $a_plant{name="plant"} + $a_p{name="p"} + +

Whole thing repeated

+ + +

Selected options repeated from copy

+ $b_animal{name="animalCopy"} + $b_plant{name="plantCopy"} + $b_p{name="pCopy"} + + + `, + }); + + await check_internal_external({ + core, + namePrefixes: ["/a_", "/b_"], + skipSingletons: true, + }); + }); + + it("references to internal and external components, new namespace", async () => { + let core = await createTestCore({ + doenetML: ` + dog + cat + mouse + + +

original: + + $(../x1{name="animal"}) + $(../y1{name="plant"}) + 3xa + $x$a + + + $(../x2{name="animal"}) + $(../y2{name="plant"}) + 4yb + $x$a + + + $(../x3{name="animal"}) + $(../y3{name="plant"}) + 5zc + $x$a + +

+ + tree + shrub + bush + +

Selected options repeated

+ $(a/animal{name="animal"}) + $(a/plant{name="plant"}) + $(a/p{name="p"}) + $(a/x{name="xx"}) + $(a/a{name="aa"}) + +

Whole thing repeated

+ + +

Selected options repeated from copy

+ $(b/animal{name="animalCopy"}) + $(b/plant{name="plantCopy"}) + $(b/p{name="pCopy"}) + $(b/x{name="xxCopy"}) + $(b/a{name="aaCopy"}) + + `, + }); + + await check_internal_external({ core, namePrefixes: ["/a/", "/b/"] }); + }); + + it("references to internal and external components, multiple layers of new namespaces", async () => { + let core = await createTestCore({ + doenetML: ` + dog + cat + mouse + + +

original: + + $(../../x1{name="animal"}) + $(../../y1{name="plant"}) + 3xa + $x$a + + + $(../../x2{name="animal"}) + $(../../y2{name="plant"}) + 4yb + $x$a + + + $(../../x3{name="animal"}) + $(../../y3{name="plant"}) + 5zc + $x$a + +

+ + tree + shrub + bush + +

Selected options repeated

+ $(s/a/animal{name="animal"}) + $(s/a/plant{name="plant"}) + $(s/a/p{name="p"}) + $(s/a/x{name="xx"}) + $(s/a/a{name="aa"}) + +

Whole thing repeated

+ + +

Selected options repeated from copy

+ $(s2/b/animal{name="animalCopy"}) + $(s2/b/plant{name="plantCopy"}) + $(s2/b/p{name="pCopy"}) + $(s2/b/x{name="xxCopy"}) + $(s2/b/a{name="aaCopy"}) + + `, + }); + await check_internal_external({ + core, + namePrefixes: ["/s/a/", "/s2/b/"], + }); + }); + + it("references to internal and external components, inconsistent new namespaces", async () => { + // not sure why would want to do this, as give inconsistent behavior + // depending on which option is chosen + // but, we handle it gracefully + let core = await createTestCore({ + doenetML: ` + dog + cat + mouse + + +

original: + + $x1{name="theanimal"} + $y1{name="theplant"} + 3xa + $thex$thea + + + $(../x2{name="animal"}) + $(../y2{name="plant"}) + 4yb + $x$a + + + $(../x3{name="animal"}) + $(../y3{name="plant"}) + 5zc + $x$a + +

+ + tree + shrub + bush + +

Selected options repeated

+ $(a/animal{name="animal"}) + $(a/plant{name="plant"}) + $(a/p{name="p"}) + $(a/x{name="xx"}) + $(a/a{name="aa"}) + +

Whole thing repeated

+

+ +

Selected options repeated from copy

+ $(b/animal{name="animalCopy"}) + $(b/plant{name="plantCopy"}) + $(b/p{name="pCopy"}) + $(b/x{name="xxCopy"}) + $(b/a{name="aaCopy"}) + + `, + }); + + await check_internal_external({ + core, + namePrefixes: ["/a/", "/b/"], + calcNegativeFromContainers: ["/p1", "/repeat"], + }); + }); + + async function check_dynamic_refs({ + core, + namePrefixes, + inputName, + }: { + core: any; + namePrefixes: string[]; + inputName: string; + }) { + async function check_items({ + question, + comeback, + response, + }: { + question: string; + comeback: string; + response: string; + }) { + const stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables[`${namePrefixes[0]}question`].stateValues.text, + ).eq(question); + expect( + stateVariables[`${namePrefixes[0]}comeback`].stateValues.text, + ).eq(comeback); + expect(stateVariables[`/pResponse`].stateValues.text).eq( + `The response: ${response}`, + ); + + expect( + stateVariables[`${namePrefixes[1]}question`].stateValues.text, + ).eq(question); + expect( + stateVariables[`${namePrefixes[1]}comeback`].stateValues.text, + ).eq(comeback); + expect(stateVariables[`/pResponse2`].stateValues.text).eq( + `The response one more time: ${response}`, + ); + } + + await check_items({ + question: "What is your name? ", + comeback: "Hello, !", + response: "", + }); + + await updateTextInputValue({ + text: "Fred", + componentName: inputName, + core, + }); + await check_items({ + question: "What is your name? Fred", + comeback: "Hello, Fred!", + response: "Fred", + }); + + await updateMathInputValue({ latex: "-1", componentName: "/n", core }); + await check_items({ + question: "What is your favorite animal? ", + comeback: "I like , too.", + response: "", + }); + + await updateTextInputValue({ + text: "dogs", + componentName: inputName, + core, + }); + await check_items({ + question: "What is your favorite animal? dogs", + comeback: "I like dogs, too.", + response: "dogs", + }); + + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items({ + question: "Anything else? ", + comeback: "To repeat: .", + response: "", + }); + + await updateTextInputValue({ + text: "Goodbye", + componentName: inputName, + core, + }); + await check_items({ + question: "Anything else? Goodbye", + comeback: "To repeat: Goodbye.", + response: "Goodbye", + }); + } + + it("dynamic internal references", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

What is your favorite animal?

+

I like , too.

+
+ +

What is your name?

+

Hello, !

+
+ +

Anything else?

+

To repeat: .

+
+
+ +

The response:

+ + + +

The response one more time:

+ `, + }); + + await check_dynamic_refs({ + core, + namePrefixes: ["/a/", "/b/"], + inputName: "/a/response", + }); + }); + + it("dynamic internal references, assign pieces", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

What is your favorite animal?

+

I like , too.

+
+ +

What is your name?

+

Hello, !

+
+ +

Anything else?

+

To repeat: .

+
+
+ +

The response:

+ + + +

The response one more time:

+ `, + }); + + await check_dynamic_refs({ + core, + namePrefixes: ["/a_", "/b_"], + inputName: "/a_question/response", + }); + }); + + it("copy case", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ positive + non-positive +

+ +

+ + negative + neither +

+ + +

$cc1

+ +

$cc2

+ + `, + }); + + async function check_items(item1: string, item2: string) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/p1`].stateValues.text).eq(item1); + expect(stateVariables[`/p3`].stateValues.text).eq(item1); + expect(stateVariables[`/p2`].stateValues.text).eq(item2); + expect(stateVariables[`/p4`].stateValues.text).eq(item2); + } + + await check_items("non-positive", "neither"); + + // enter 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items("positive", "positive"); + + // enter -1 + await updateMathInputValue({ latex: "-1", componentName: "/n", core }); + await check_items("non-positive", "negative"); + + // enter 0 + await updateMathInputValue({ latex: "0", componentName: "/n", core }); + await check_items("non-positive", "neither"); + }); + + it("copy else", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ hello + bye +

+ +

+ hello + oops + +

+ +

$cc1

+ +

$cc2

+ + `, + }); + + async function check_items(item1: string, item2: string) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/p1`].stateValues.text).eq(item1); + expect(stateVariables[`/p3`].stateValues.text).eq(item1); + expect(stateVariables[`/p2`].stateValues.text).eq(item2); + expect(stateVariables[`/p4`].stateValues.text).eq(item2); + } + + await check_items("bye", "bye"); + + // enter 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items("hello", "oops"); + + // enter -1 + await updateMathInputValue({ latex: "-1", componentName: "/n", core }); + await check_items("bye", "hello"); + + // enter 0 + await updateMathInputValue({ latex: "0", componentName: "/n", core }); + await check_items("bye", "bye"); + }); + + it("conditional contents hide dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + +

a: + dog + cat + mouse +

+

b: + dog + cat + mouse +

+

a1:

+

b1:

+ `, + }); + + async function check_items(item: string, hidden: string[]) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/pa`].stateValues.text).eq( + `a: ${hidden.includes("a") ? "" : item}`, + ); + expect(stateVariables[`/pa1`].stateValues.text).eq(`a1: ${item}`); + expect(stateVariables[`/pb`].stateValues.text).eq( + `b: ${hidden.includes("b") ? "" : item}`, + ); + expect(stateVariables[`/pb1`].stateValues.text).eq(`b1: ${item}`); + } + + await check_items("mouse", ["b"]); + + // enter 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items("cat", ["b"]); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + await check_items("cat", ["a"]); + + // enter -3 + await updateMathInputValue({ latex: "-3", componentName: "/n", core }); + await check_items("dog", ["a"]); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/h2", + core, + }); + + await check_items("dog", ["b"]); + }); + + it("string and blank strings in case and else", async () => { + let core = await createTestCore({ + doenetML: ` + + foxjumps + elephanttrumpets + + + +

a: + The $animal1 $verb1. + The $animal2 $verb2. +

+ +

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

+ +

pieces:

+ +

b1: $b{name="b1"}

+

c1: $c{name="c1"}

+

d1: $d{name="d1"}

+

e1: $e{name="e1"}

+ + `, + }); + + async function check_items(animal: string, verb: string) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pa"].stateValues.text).eq( + `a: The ${animal} ${verb}.`, + ); + expect(stateVariables["/pa1"].stateValues.text).eq( + `a1: The ${animal} ${verb}.`, + ); + expect(stateVariables["/pPieces"].stateValues.text).eq( + `pieces: The ${animal} ${verb}.`, + ); + + expect(stateVariables["/pb1"].stateValues.text).eq("b1: "); + expect(stateVariables["/pc1"].stateValues.text).eq(`c1: ${animal}`); + expect(stateVariables["/pd1"].stateValues.text).eq(`d1: ${verb}`); + expect(stateVariables["/pe1"].stateValues.text).eq("e1: "); + + expect(stateVariables["/a11"]).eq(undefined); + expect(stateVariables["/a12"].stateValues.text).eq(animal); + expect(stateVariables["/a13"].stateValues.text).eq(verb); + expect(stateVariables["/a14"]).eq(undefined); + + expect(stateVariables["/b1"]).eq(undefined); + expect(stateVariables["/c1"].stateValues.text).eq(animal); + expect(stateVariables["/d1"].stateValues.text).eq(verb); + expect(stateVariables["/e1"]).eq(undefined); + } + + await check_items("elephant", "trumpets"); + + // enter 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items("fox", "jumps"); + + // enter 0 + await updateMathInputValue({ latex: "0", componentName: "/n", core }); + await check_items("elephant", "trumpets"); + }); + + it("copy with invalid source gets expanded", async () => { + let core = await createTestCore({ + doenetML: ` +
+ + before + + nothing: $nada + + after +
+ `, + }); + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/s"].activeChildren).eqls([ + "\n ", + { componentName: "/n", componentType: "mathInput" }, + "\n before\n ", + "nothing: ", + "\n after\n", + ]); + }); + + it("use original names if no assignNames", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

We have a first winner!

+
+ + + +

Just emphasizing that we have that first winner!

+
+ +

We have a second winner!

+
+ +

We have a third winner!

+
+ +

We have no winner.

+
+
+ `, + }); + + async function check_items(num_winners: number) { + const stateVariables = await returnAllStateVariables(core); + + if (num_winners > 0) { + expect(stateVariables["/winner1"].stateValues.text).eq( + "first winner", + ); + expect(stateVariables["/p1"].stateValues.text).eq( + "We have a first winner!", + ); + } else { + expect( + stateVariables["/winner1"] === undefined || + stateVariables["/winner1"].stateValues + .isInactiveCompositeReplacement, + ).eq(true); + expect( + stateVariables["/p1"] === undefined || + stateVariables["/p1"].stateValues + .isInactiveCompositeReplacement, + ).eq(true); + } + + if (num_winners === 1) { + expect(stateVariables["/winner1b"].stateValues.text).eq( + "first winner", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "Just emphasizing that we have that first winner!", + ); + } else { + expect(stateVariables["/winner1b"]).eq(undefined); + expect(stateVariables["/p2"]).eq(undefined); + } + + if (num_winners === 2) { + expect(stateVariables["/winner2"].stateValues.text).eq( + "second winner", + ); + expect(stateVariables["/p3"].stateValues.text).eq( + "We have a second winner!", + ); + } else { + expect(stateVariables["/winner2"]).eq(undefined); + expect(stateVariables["/p3"]).eq(undefined); + } + + if (num_winners > 2) { + expect(stateVariables["/winner3"].stateValues.text).eq( + "third winner", + ); + expect(stateVariables["/p4"].stateValues.text).eq( + "We have a third winner!", + ); + } else { + expect(stateVariables["/winner3"]).eq(undefined); + expect(stateVariables["/p4"]).eq(undefined); + } + + if (num_winners === 0) { + expect(stateVariables["/winner0"].stateValues.text).eq( + "no winner", + ); + expect(stateVariables["/p5"].stateValues.text).eq( + "We have no winner.", + ); + } else { + expect(stateVariables["/winner0"]).eq(undefined); + expect(stateVariables["/p5"]).eq(undefined); + } + } + + await check_items(0); + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items(1); + + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items(2); + + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items(3); + + await updateMathInputValue({ latex: "x", componentName: "/n", core }); + await check_items(0); + }); + + it("primitive replacements removed from text when conditional content is hidden", async () => { + let core = await createTestCore({ + doenetML: ` +true + +

We have apples, bananas, pineapples, and mangos.

+ + + `, + }); + + async function check_items(h: boolean) { + const stateVariables = await returnAllStateVariables(core); + + let phrase = h + ? "We have bananas, pineapples, and mangos." + : "We have apples, bananas, and mangos."; + + expect(stateVariables["/p"].stateValues.text).eq(phrase); + expect(stateVariables["/text"].stateValues.text).eq(phrase); + } + + await check_items(true); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h", + core, + }); + await check_items(false); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h", + core, + }); + await check_items(true); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/integer.test.ts b/packages/doenetml-worker/src/test/tagSpecific/integer.test.ts new file mode 100644 index 000000000..94b8bfe5d --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/integer.test.ts @@ -0,0 +1,133 @@ +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("Integer tag tests", async () => { + it("1.2+1.1", async () => { + let core = await createTestCore({ + doenetML: ` + $_integer1{name="int"} + 1.2+1.1 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/int"].stateValues.value).eq(2); + expect(stateVariables["/_integer1"].stateValues.value).eq(2); + }); + + it(`non-numeric value`, async () => { + let core = await createTestCore({ + doenetML: ` + $_integer1{name="int"} + x+1 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/int"].stateValues.value).eqls(NaN); + expect(stateVariables["/_integer1"].stateValues.value).eqls(NaN); + }); + + it(`entering non-integer values dynamically`, async () => { + let core = await createTestCore({ + doenetML: ` + $mi + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq(""); + + await updateMathInputValue({ + latex: "-6.5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(-6); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("-6.5"); + + await updateMathInputValue({ + latex: "-6.5x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("-6.5x"); + + await updateMathInputValue({ + latex: "9.5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(10); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("9.5"); + }); + + it(`entering non-integer through inverse`, async () => { + let core = await createTestCore({ + doenetML: ` + 5 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("5"); + + await updateMathInputValue({ + latex: "-6.5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(-6); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("-6"); + + await updateMathInputValue({ + latex: "-6.5x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("NaN"); + + // Note: change to 3 and then 31 to verify bug doesn't reappear + await updateMathInputValue({ + latex: "3", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("3"); + + await updateMathInputValue({ + latex: "31", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(31); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("31"); + + await updateMathInputValue({ + latex: "31.5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(32); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("32"); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/lorem.test.ts b/packages/doenetml-worker/src/test/tagSpecific/lorem.test.ts new file mode 100644 index 000000000..a0506e480 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/lorem.test.ts @@ -0,0 +1,242 @@ +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("lorem tag tests", async () => { + it("paragraphs, sentences, and words", async () => { + let core = await createTestCore({ + doenetML: ` +
+ Paragraphs + +

Number of paragraphs:

+ + +
+ +
+ Sentences + +

Number of sentences:

+ +

+ +
+ +
+ Words + +

Number of words:

+ +

+
+ +

+ $(words/numWords.value{assignNames="numWords"}) +

+ `, + }); + + let names = ["a", "b", "c", "d", "e", "f"]; + + let stateVariables = await returnAllStateVariables(core); + + let nParagraphs = 3, + nSentences = 3, + nWords = 3; + + expect(stateVariables["/paragraphs/lPars"].replacements!.length).eq( + nParagraphs, + ); + expect(stateVariables["/sentences/lSens"].replacements!.length).eq( + 2 * nSentences - 1, + ); + expect(stateVariables["/words/lWords"].replacements!.length).eq( + 2 * nWords - 1, + ); + + for (let [ind, repl] of stateVariables[ + "/paragraphs/lPars" + ].replacements!.entries()) { + expect( + stateVariables[`/paragraphs/${names[ind]}`].stateValues.text, + ).eq(stateVariables[repl.componentName].activeChildren[0]); + } + + for (let [ind, repl] of stateVariables[ + "/sentences/lSens" + ].replacements!.entries()) { + if (ind % 2 === 1) { + continue; + } + + expect( + stateVariables[`/sentences/${names[ind / 2]}`].stateValues.text, + ).eq(stateVariables[repl.componentName].activeChildren[0]); + } + + for (let [ind, repl] of stateVariables[ + "/words/lWords" + ].replacements!.entries()) { + if (ind % 2 === 1) { + continue; + } + + expect( + stateVariables[`/words/${names[ind / 2]}`].stateValues.text, + ).eq(stateVariables[repl.componentName].activeChildren[0]); + } + + nParagraphs = 6; + nSentences = 2; + nWords = 5; + + await updateMathInputValue({ + latex: `${nParagraphs}`, + componentName: "/paragraphs/numPars", + core, + }); + await updateMathInputValue({ + latex: `${nSentences}`, + componentName: "/sentences/numSens", + core, + }); + await updateMathInputValue({ + latex: `${nWords}`, + componentName: "/words/numWords", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/paragraphs/lPars"].replacements!.length).eq( + nParagraphs, + ); + expect(stateVariables["/sentences/lSens"].replacements!.length).eq( + 2 * nSentences - 1, + ); + expect(stateVariables["/words/lWords"].replacements!.length).eq( + 2 * nWords - 1, + ); + + for (let [ind, repl] of stateVariables[ + "/paragraphs/lPars" + ].replacements!.entries()) { + expect( + stateVariables[`/paragraphs/${names[ind]}`].stateValues.text, + ).eq(stateVariables[repl.componentName].activeChildren[0]); + } + + for (let [ind, repl] of stateVariables[ + "/sentences/lSens" + ].replacements!.entries()) { + if (ind % 2 === 1) { + continue; + } + + expect( + stateVariables[`/sentences/${names[ind / 2]}`].stateValues.text, + ).eq(stateVariables[repl.componentName].activeChildren[0]); + } + + for (let [ind, repl] of stateVariables[ + "/words/lWords" + ].replacements!.entries()) { + if (ind % 2 === 1) { + continue; + } + + expect( + stateVariables[`/words/${names[ind / 2]}`].stateValues.text, + ).eq(stateVariables[repl.componentName].activeChildren[0]); + } + }); + + it("changes only with variant", async () => { + let core = await createTestCore({ + doenetML: ` + + + `, + requestedVariantIndex: 1, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/lPars"].replacements!.length).eq(1); + + let paragraph0 = + stateVariables[ + stateVariables["/lPars"].replacements![0].componentName + ].activeChildren[0]; + + expect(stateVariables["/a"].stateValues.text).eq(paragraph0); + + core = await createTestCore({ + doenetML: ` + + + `, + requestedVariantIndex: 1, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/lPars"].replacements!.length).eq(1); + + expect( + stateVariables[ + stateVariables["/lPars"].replacements![0].componentName + ].activeChildren[0], + ).eq(paragraph0); + + expect(stateVariables["/a"].stateValues.text).eq(paragraph0); + + core = await createTestCore({ + doenetML: ` + + + `, + requestedVariantIndex: 2, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/lPars"].replacements!.length).eq(1); + + let paragraph1 = + stateVariables[ + stateVariables["/lPars"].replacements![0].componentName + ].activeChildren[0]; + expect(paragraph1).not.eq(paragraph0); + + expect(stateVariables["/a"].stateValues.text).eq(paragraph1); + + core = await createTestCore({ + doenetML: ` + d + + + `, + requestedVariantIndex: 2, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/lPars"].replacements!.length).eq(1); + + expect( + stateVariables[ + stateVariables["/lPars"].replacements![0].componentName + ].activeChildren[0], + ).eq(paragraph1); + + expect(stateVariables["/a"].stateValues.text).eq(paragraph1); + }); +}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/matchespattern.cy.js b/packages/doenetml-worker/src/test/tagSpecific/matchespattern.test.ts similarity index 59% rename from packages/test-cypress/cypress/e2e/tagSpecific/matchespattern.cy.js rename to packages/doenetml-worker/src/test/tagSpecific/matchespattern.test.ts index 76fc25dc3..437bdf39d 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/matchespattern.cy.js +++ b/packages/doenetml-worker/src/test/tagSpecific/matchespattern.test.ts @@ -1,20 +1,20 @@ -import { cesc } from "@doenet/utils"; - -describe("MatchesPattern Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("match linear pattern", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a +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("MatchesPattern tag tests", async () => { + it("match linear pattern", async () => { + let core = await createTestCore({ + doenetML: `

Pattern: ()x+()

Expression:

-

Default settings: $expr @@ -48,13 +48,8 @@ describe("MatchesPattern Tag Tests", function () { `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - let matchNames = { default: ["dm1", "dm2"], noperm: ["npm1", "npm2"], @@ -76,7 +71,7 @@ describe("MatchesPattern Tag Tests", function () { x: { default: false, noperm: false, - implicitIdents: [1, 0], + implicitIdents: ["1", "0"], requireNumeric: false, requireVariable: false, excludeX: false, @@ -84,48 +79,48 @@ describe("MatchesPattern Tag Tests", function () { "x+y": { default: false, noperm: false, - implicitIdents: [1, "y"], + implicitIdents: ["1", "y"], requireNumeric: false, requireVariable: false, excludeX: false, }, "2x+y": { - default: [2, "y"], - noperm: [2, "y"], - implicitIdents: [2, "y"], + default: ["2", "y"], + noperm: ["2", "y"], + implicitIdents: ["2", "y"], requireNumeric: false, requireVariable: false, excludeX: false, }, "y+2x": { - default: [2, "y"], + default: ["2", "y"], noperm: false, - implicitIdents: [2, "y"], + implicitIdents: ["2", "y"], requireNumeric: false, requireVariable: false, excludeX: false, }, "x*2+y": { - default: [2, "y"], + default: ["2", "y"], noperm: false, - implicitIdents: [2, "y"], + implicitIdents: ["2", "y"], requireNumeric: false, requireVariable: false, excludeX: false, }, - "(y+z)x+7+e^q+5": { - default: ["y+z", "7+eq+5"], - noperm: ["y+z", "7+eq+5"], - implicitIdents: ["y+z", "7+eq+5"], + "(y+z)x+7+e^{q+5}": { + default: ["y+z", "7+e^{q+5}"], + noperm: ["y+z", "7+e^{q+5}"], + implicitIdents: ["y+z", "7+e^{q+5}"], requireNumeric: false, requireVariable: false, excludeX: false, }, - "pi x+sqrt3": { - default: ["Ο€", "√3"], - noperm: ["Ο€", "√3"], - implicitIdents: ["Ο€", "√3"], - requireNumeric: ["Ο€", "√3"], + "\\pi x+\\sqrt{3}": { + default: ["\\pi", "\\sqrt{3}"], + noperm: ["\\pi", "\\sqrt{3}"], + implicitIdents: ["\\pi", "\\sqrt{3}"], + requireNumeric: ["\\pi", "\\sqrt{3}"], requireVariable: false, excludeX: false, }, @@ -179,52 +174,52 @@ describe("MatchesPattern Tag Tests", function () { }, }; - let b = false; - for (let expr in desiredResults) { - cy.log(`trying: ${expr}`); - cy.get(cesc("#\\/expr") + " textarea").type( - `{ctrl+home}{ctrl+shift+end}{backspace}${expr}{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/bi")).click(); - b = !b; - cy.get(cesc("#\\/b")).should("have.text", b.toString()); // to make sure change occured + await updateMathInputValue({ + latex: expr, + componentName: "/expr", + core, + }); + let stateVariables = await returnAllStateVariables(core); let dResults = desiredResults[expr]; for (let name in dResults) { let res = dResults[name]; if (res) { - cy.get(cesc(`#\\/${name}`)).should("have.text", "true"); - cy.get(cesc(`#\\/${matchNames[name][0]}`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[0]); - cy.get(cesc(`#\\/${matchNames[name][1]}`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[1]); + expect(stateVariables[`/${name}`].stateValues.value).to.be + .true; + expect( + cleanLatex( + stateVariables[`/${matchNames[name][0]}`] + .stateValues.latex, + ), + ).eq(res[0]); + expect( + cleanLatex( + stateVariables[`/${matchNames[name][1]}`] + .stateValues.latex, + ), + ).eq(res[1]); } else { - cy.get(cesc(`#\\/${name}`)).should("have.text", "false"); - cy.get(cesc(`#\\/${matchNames[name][0]}`)).should( - "not.exist", + expect(stateVariables[`/${name}`].stateValues.value).to.be + .false; + expect(stateVariables[`/${matchNames[name][0]}`]).eq( + undefined, ); - cy.get(cesc(`#\\/${matchNames[name][1]}`)).should( - "not.exist", + expect(stateVariables[`/${matchNames[name][1]}`]).eq( + undefined, ); } } } }); - it("match quadratic pattern, base test", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("match quadratic pattern, base test", async () => { + let core = await createTestCore({ + doenetML: `

Pattern: ()x^2+()x+()

Expression:

-

Default settings: $expr @@ -258,13 +253,8 @@ describe("MatchesPattern Tag Tests", function () { `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - let matchNames = { default: ["dm1", "dm2", "dm3"], noperm: ["npm1", "npm2", "npm3"], @@ -299,23 +289,23 @@ describe("MatchesPattern Tag Tests", function () { requireVariable: false, excludeX: false, }, - "x^2{rightArrow}+x": { + "x^2+x": { default: false, noperm: false, - implicitIdents: [1, 1, 0], + implicitIdents: ["1", "1", "0"], requireNumeric: false, requireVariable: false, excludeX: false, }, - "1x^2{rightArrow}+1x+0": { - default: [1, 1, 0], - noperm: [1, 1, 0], - implicitIdents: [1, 1, 0], - requireNumeric: [1, 1, 0], + "1x^2+1x+0": { + default: ["1", "1", "0"], + noperm: ["1", "1", "0"], + implicitIdents: ["1", "1", "0"], + requireNumeric: ["1", "1", "0"], requireVariable: false, excludeX: false, }, - "ax^2{rightArrow}+bx+c": { + "ax^2+bx+c": { default: ["a", "b", "c"], noperm: ["a", "b", "c"], implicitIdents: ["a", "b", "c"], @@ -323,7 +313,7 @@ describe("MatchesPattern Tag Tests", function () { requireVariable: ["a", "b", "c"], excludeX: ["a", "b", "c"], }, - "ax^2{rightArrow}+c+bx": { + "ax^2+c+bx": { default: ["a", "b", "c"], noperm: false, implicitIdents: ["a", "b", "c"], @@ -331,7 +321,7 @@ describe("MatchesPattern Tag Tests", function () { requireVariable: ["a", "b", "c"], excludeX: ["a", "b", "c"], }, - "xx^2{rightArrow}+bx+c": { + "xx^2+bx+c": { default: ["x", "b", "c"], noperm: ["x", "b", "c"], implicitIdents: ["x", "b", "c"], @@ -341,53 +331,53 @@ describe("MatchesPattern Tag Tests", function () { }, }; - let b = false; - for (let expr in desiredResults) { - cy.log(`trying: ${expr}`); - cy.get(cesc("#\\/expr") + " textarea").type( - `{ctrl+home}{ctrl+shift+end}{backspace}${expr}{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/bi")).click(); - b = !b; - cy.get(cesc("#\\/b")).should("have.text", b.toString()); // to make sure change occured + await updateMathInputValue({ + latex: expr, + componentName: "/expr", + core, + }); + let stateVariables = await returnAllStateVariables(core); let dResults = desiredResults[expr]; for (let name in dResults) { let res = dResults[name]; if (res) { - cy.get(cesc(`#\\/${name}`)).should("have.text", "true"); - cy.get(cesc(`#\\/${matchNames[name][0]}`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[0]); - cy.get(cesc(`#\\/${matchNames[name][1]}`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[1]); + expect(stateVariables[`/${name}`].stateValues.value).to.be + .true; + expect( + cleanLatex( + stateVariables[`/${matchNames[name][0]}`] + .stateValues.latex, + ), + ).eq(res[0]); + expect( + cleanLatex( + stateVariables[`/${matchNames[name][1]}`] + .stateValues.latex, + ), + ).eq(res[1]); } else { - cy.get(cesc(`#\\/${name}`)).should("have.text", "false"); - cy.get(cesc(`#\\/${matchNames[name][0]}`)).should( - "not.exist", + expect(stateVariables[`/${name}`].stateValues.value).to.be + .false; + expect(stateVariables[`/${matchNames[name][0]}`]).eq( + undefined, ); - cy.get(cesc(`#\\/${matchNames[name][1]}`)).should( - "not.exist", + expect(stateVariables[`/${matchNames[name][1]}`]).eq( + undefined, ); } } } }); - it("match quadratic pattern, combine matches for flexibility", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("match quadratic pattern, combine matches for flexibility", async () => { + let core = await createTestCore({ + doenetML: `

Pattern 1: ()x^2+()x+()

Pattern 2: ()x^2+()

Expression:

-

base: $expr @@ -422,13 +412,8 @@ describe("MatchesPattern Tag Tests", function () {

`, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - let matchNames = { base: ["bm1", "bm2", "bm3"], requireNumeric: ["rnm1", "rnm2", "rnm3"], @@ -442,120 +427,132 @@ describe("MatchesPattern Tag Tests", function () { excludeX: false, }, "x^2": { - base: [1, 0, 0], - requireNumeric: [1, 0, 0], - excludeX: [1, 0, 0], - }, - "x^2{rightArrow}+x": { - base: [1, 1, 0], - requireNumeric: [1, 1, 0], - excludeX: [1, 1, 0], - }, - "x^2{rightArrow}+x+1": { - base: [1, 1, 1], - requireNumeric: [1, 1, 1], - excludeX: [1, 1, 1], - }, - "3x^2{rightArrow}-5x+pi": { - base: [3, "βˆ’5", "pi"], - requireNumeric: [3, "βˆ’5", "pi"], - excludeX: [3, "βˆ’5", "pi"], - }, - "ax^2{rightArrow}+bx+c": { + base: ["1", "0", "0"], + requireNumeric: ["1", "0", "0"], + excludeX: ["1", "0", "0"], + }, + "x^2+x": { + base: ["1", "1", "0"], + requireNumeric: ["1", "1", "0"], + excludeX: ["1", "1", "0"], + }, + "x^2+x+1": { + base: ["1", "1", "1"], + requireNumeric: ["1", "1", "1"], + excludeX: ["1", "1", "1"], + }, + "3x^2-5x+\\pi": { + base: ["3", "-5", "\\pi"], + requireNumeric: ["3", "-5", "\\pi"], + excludeX: ["3", "-5", "\\pi"], + }, + "ax^2+bx+c": { base: ["a", "b", "c"], requireNumeric: false, excludeX: ["a", "b", "c"], }, - "ax^2{rightArrow}+c": { + "ax^2+c": { base: ["a", "0", "c"], requireNumeric: false, excludeX: ["a", "0", "c"], }, - "xx^2{rightArrow}+c": { + "xx^2+c": { base: ["x", "0", "c"], requireNumeric: false, excludeX: false, }, - "xx^2{rightArrow}+bx+c": { + "xx^2+bx+c": { base: ["x", "b", "c"], requireNumeric: false, excludeX: false, }, - "3/2{rightArrow}x^2{rightArrow}+5/7{rightArrow}x+2/3": { - base: ["32", "57", "23"], - requireNumeric: ["32", "57", "23"], - excludeX: ["32", "57", "23"], + "3/2x^2+5/7x+2/3": { + base: ["\\frac{3}{2}", "\\frac{5}{7}", "\\frac{2}{3}"], + requireNumeric: [ + "\\frac{3}{2}", + "\\frac{5}{7}", + "\\frac{2}{3}", + ], + excludeX: ["\\frac{3}{2}", "\\frac{5}{7}", "\\frac{2}{3}"], }, - "3/2{rightArrow}x^2{rightArrow}+2/3": { - base: ["32", "0", "23"], - requireNumeric: ["32", "0", "23"], - excludeX: ["32", "0", "23"], + "3/2x^2+2/3": { + base: ["\\frac{3}{2}", "0", "\\frac{2}{3}"], + requireNumeric: ["\\frac{3}{2}", "0", "\\frac{2}{3}"], + excludeX: ["\\frac{3}{2}", "0", "\\frac{2}{3}"], }, }; - let b = false; - for (let expr in desiredResults) { - cy.log(`trying: ${expr}`); - cy.get(cesc("#\\/expr") + " textarea").type( - `{ctrl+home}{ctrl+shift+end}{backspace}${expr}{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/bi")).click(); - b = !b; - cy.get(cesc("#\\/b")).should("have.text", b.toString()); // to make sure change occured + await updateMathInputValue({ + latex: expr, + componentName: "/expr", + core, + }); + let stateVariables = await returnAllStateVariables(core); let dResults = desiredResults[expr]; for (let name in dResults) { let res = dResults[name]; if (res) { - cy.get(cesc(`#\\/${name}`)).should("have.text", "true"); - cy.get(cesc(`#\\/${matchNames[name][0]}`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[0]); - cy.get(cesc(`#\\/${matchNames[name][1]}`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[1]); + expect(stateVariables[`/${name}`].stateValues.value).to.be + .true; + let match1 = stateVariables[`/${matchNames[name][0]}`]; + if (match1.componentType === "copy") { + match1 = + stateVariables[ + match1.replacements![0].componentName + ]; + } + expect(cleanLatex(match1.stateValues.latex)).eq(res[0]); + let match2 = stateVariables[`/${matchNames[name][1]}`]; + if (match2.componentType === "copy") { + match2 = + stateVariables[ + match2.replacements![0].componentName + ]; + } + expect(cleanLatex(match2.stateValues.latex)).eq(res[1]); + let match3 = stateVariables[`/${matchNames[name][2]}`]; + if (match3.componentType === "copy") { + match3 = + stateVariables[ + match3.replacements![0].componentName + ]; + } + expect(cleanLatex(match3.stateValues.latex)).eq(res[2]); } else { - cy.get(cesc(`#\\/${name}`)).should("have.text", "false"); - cy.get(cesc(`#\\/${matchNames[name][0]}`)).should( - "not.exist", + expect(stateVariables[`/${name}`].stateValues.value).to.be + .false; + expect(stateVariables[`/${matchNames[name][0]}`]).eq( + undefined, + ); + expect(stateVariables[`/${matchNames[name][1]}`]).eq( + undefined, ); - cy.get(cesc(`#\\/${matchNames[name][1]}`)).should( - "not.exist", + expect(stateVariables[`/${matchNames[name][2]}`]).eq( + undefined, ); } } } }); - it("handle case with no pattern specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("handle case with no pattern specified", async () => { + let core = await createTestCore({ + doenetML: `

hello

- - `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + let stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/mp")).should("have.text", "false"); + expect(stateVariables[`/mp`].stateValues.value).to.be.false; }); - it("works with string or multiple children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("works with string or multiple children", async () => { + let core = await createTestCore({ + doenetML: `

e^(x+2)

Matches:

e^(x+2)

@@ -563,34 +560,26 @@ describe("MatchesPattern Tag Tests", function () { `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mps")).should("have.text", "true"); - cy.get(cesc("#\\/mpsm1") + " .mjx-mrow") - .eq(0) - .should("have.text", "e"); - cy.get(cesc("#\\/mpsm2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+2"); - cy.get(cesc("#\\/mpm")).should("have.text", "true"); - cy.get(cesc("#\\/mpmm1") + " .mjx-mrow") - .eq(0) - .should("have.text", "e"); - cy.get(cesc("#\\/mpmm2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+2"); + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/mps`].stateValues.value).to.be.true; + expect(cleanLatex(stateVariables[`/mpsm1`].stateValues.latex)).eq("e"); + expect(cleanLatex(stateVariables[`/mpsm2`].stateValues.latex)).eq( + "x+2", + ); + + expect(stateVariables[`/mpm`].stateValues.value).to.be.true; + expect(cleanLatex(stateVariables[`/mpmm1`].stateValues.latex)).eq("e"); + expect(cleanLatex(stateVariables[`/mpmm2`].stateValues.latex)).eq( + "x+2", + ); }); - it("match expression with blanks", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` + it("match expression with blanks", async () => { + let core = await createTestCore({ + doenetML: ` a

Pattern: <

Expression:

@@ -603,13 +592,8 @@ describe("MatchesPattern Tag Tests", function () { `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - let desiredResults = { "": { default: false, @@ -647,58 +631,70 @@ describe("MatchesPattern Tag Tests", function () { default: false, blanks: ["\uff3f", "c"], }, - "q/r{rightArrow} < st": { - default: ["qr", "st"], - blanks: ["qr", "st"], + "q/r < st": { + default: ["\\frac{q}{r}", "st"], + blanks: ["\\frac{q}{r}", "st"], }, - "q/{rightArrow} < st": { + "q/ < st": { default: false, - blanks: ["q\uff3f", "st"], + blanks: ["\\frac{q}{\uff3f}", "st"], }, }; for (let expr in desiredResults) { - cy.log(`trying: ${expr}`); - cy.get(cesc("#\\/expr") + " textarea").type( - `{ctrl+home}{ctrl+shift+end}{backspace}${expr}{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/matchBlanks")).click(); - cy.get(cesc("#\\/matchBlanks2")).should("have.text", "true"); // to make sure change occured + await updateMathInputValue({ + latex: expr, + componentName: "/expr", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/matchBlanks", + core, + }); + + let stateVariables = await returnAllStateVariables(core); let dResults = desiredResults[expr]; let res = dResults.blanks; if (res) { - cy.get(cesc(`#\\/match`)).should("have.text", "true"); - cy.get(cesc(`#\\/m1`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[0]); - cy.get(cesc(`#\\/m2`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[1]); + expect(stateVariables[`/match`].stateValues.value).to.be.true; + expect(cleanLatex(stateVariables[`/m1`].stateValues.latex)).eq( + res[0], + ); + expect(cleanLatex(stateVariables[`/m2`].stateValues.latex)).eq( + res[1], + ); } else { - cy.get(cesc(`#\\/match`)).should("have.text", "false"); - cy.get(cesc(`#\\/m1`)).should("not.exist"); - cy.get(cesc(`#\\/m2`)).should("not.exist"); + expect(stateVariables[`/match`].stateValues.value).to.be.false; + expect(stateVariables[`/m1`]).eq(undefined); + expect(stateVariables[`/m2`]).eq(undefined); } - cy.get(cesc("#\\/matchBlanks")).click(); - cy.get(cesc("#\\/matchBlanks2")).should("have.text", "false"); // to make sure change occured + await updateBooleanInputValue({ + boolean: false, + componentName: "/matchBlanks", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + dResults = desiredResults[expr]; res = dResults.default; if (res) { - cy.get(cesc(`#\\/match`)).should("have.text", "true"); - cy.get(cesc(`#\\/m1`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[0]); - cy.get(cesc(`#\\/m2`) + ` .mjx-mrow`) - .eq(0) - .should("have.text", res[1]); + expect(stateVariables[`/match`].stateValues.value).to.be.true; + expect(cleanLatex(stateVariables[`/m1`].stateValues.latex)).eq( + res[0], + ); + expect(cleanLatex(stateVariables[`/m2`].stateValues.latex)).eq( + res[1], + ); } else { - cy.get(cesc(`#\\/match`)).should("have.text", "false"); - cy.get(cesc(`#\\/m1`)).should("not.exist"); - cy.get(cesc(`#\\/m2`)).should("not.exist"); + expect(stateVariables[`/match`].stateValues.value).to.be.false; + expect(stateVariables[`/m1`]).eq(undefined); + expect(stateVariables[`/m2`]).eq(undefined); } } }); diff --git a/packages/doenetml-worker/src/test/tagSpecific/math.test.ts b/packages/doenetml-worker/src/test/tagSpecific/math.test.ts new file mode 100644 index 000000000..55e581617 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/math.test.ts @@ -0,0 +1,9134 @@ +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("Math tag tests", async () => { + it("1+1", async () => { + let core = await createTestCore({ + doenetML: ` + 1+1 + 1+1 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls(["+", 1, 1]); + expect(stateVariables["/m1s"].stateValues.value.tree).eqls(2); + }); + + it("string math string", async () => { + let core = await createTestCore({ + doenetML: ` + 3x+1+5 + 3x+1+5 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + ["*", 3, ["+", "x", 1]], + 5, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "+", + 5, + ["*", 3, ["+", "x", 1]], + ]); + }); + + it("hidden string copy/math string", async () => { + let core = await createTestCore({ + doenetML: ` + x+1 + 3$m1{name="m1a"} + 5 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/m1a"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + ["*", 3, ["+", "x", 1]], + 5, + ]); + expect(stateVariables["/m1"].stateValues.hide).eq(true); + expect(stateVariables["/m1a"].stateValues.hide).eq(true); + expect(stateVariables["/m2"].stateValues.hide).eq(false); + }); + + it("math underscore when no value", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eq("οΌΏ"); + expect(stateVariables["/m2"].stateValues.value.tree).eq("οΌΏ"); + expect(stateVariables["/m3"].stateValues.value.tree).eq("οΌΏ"); + }); + + it("format latex", async () => { + let core = await createTestCore({ + doenetML: ` + \\frac{x}{z} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "/", + "x", + "z", + ]); + }); + + it("copy latex property", async () => { + let core = await createTestCore({ + doenetML: ` + x/y + $m.latex{assignNames="l1"} + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/l1"].stateValues.value).eq("\\frac{x}{y}"); + expect(stateVariables["/l2"].stateValues.value).eq("\\frac{x}{y}"); + expect(stateVariables["/l3"].stateValues.value).eq("\\frac{x}{y}"); + }); + + it("math with internal and external copies", async () => { + let core = await createTestCore({ + doenetML: ` + x + $x + $z + z + $a{name="a2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + "z", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + "z", + ]); + }); + + it("point adapts into a math", async () => { + let core = await createTestCore({ + doenetML: ` + a + 3 + 2 + $_point1 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m"].stateValues.value.tree).eq(5); + }); + + it("adjacent string children in math", async () => { + let core = await createTestCore({ + doenetML: ` + 23 + ($m, 3) + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].activeChildren[0]).eq("2"); + expect(stateVariables["/m"].activeChildren[1]).eq("3"); + expect(stateVariables["/m"].stateValues.value.tree).eq(6); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(6); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(3); + + // move point to (7,9) + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 7, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + // Since we mark the component to ignore changes to defining children, + // the activeChildren might not be changed + // expect(stateVariables["/m1"].activeChildren[0]).eq("7"); + // expect(stateVariables["/m1"].activeChildren[1]).eq(""); + expect(stateVariables["/m"].stateValues.value.tree).eq(7); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(7); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(9); + }); + + it("math displayed rounded to 3 significant digits by default", async () => { + let core = await createTestCore({ + doenetML: ` + 1.001 + 0.3004 x + 4pi + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eq(1.001); + expect(stateVariables["/m1"].stateValues.valueForDisplay.tree).eq(1); + expect(stateVariables["/m1"].stateValues.latex).eq("1"); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + ["*", 0.3004, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/m2"].stateValues.valueForDisplay.tree).eqls([ + "+", + ["*", 0.3, "x"], + ["*", 4, "pi"], + ]); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "0.3x+4\\pi", + ); + }); + + it("mutual references of format", async () => { + let core = await createTestCore({ + doenetML: ` + + \\sin(y) + + sin(x) + + + + sin(u) + + \\sin(v) + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/a"].stateValues.latex)).eq( + "\\sin(x)\\sin(y)", + ); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "\\sin(u)\\sin(v)", + ); + expect(stateVariables["/formata"].stateValues.value).eq("latex"); + expect(stateVariables["/formatb"].stateValues.value).eq("text"); + expect(stateVariables["/formatc"].stateValues.value).eq("text"); + expect(stateVariables["/formatd"].stateValues.value).eq("latex"); + + // change format of second to latex + await updateTextInputValue({ + componentName: "/ti2", + text: "latex", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/a"].stateValues.latex)).eq( + "insx\\sin(y)", + ); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "insu\\sin(v)", + ); + expect(stateVariables["/formata"].stateValues.value).eq("latex"); + expect(stateVariables["/formatb"].stateValues.value).eq("latex"); + expect(stateVariables["/formatc"].stateValues.value).eq("latex"); + expect(stateVariables["/formatd"].stateValues.value).eq("latex"); + + // change format of first to text + await updateTextInputValue({ + componentName: "/ti1", + text: "text", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/a"].stateValues.latex)).eq("οΌΏ"); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq("sinuοΌΏ"); + expect(stateVariables["/formata"].stateValues.value).eq("text"); + expect(stateVariables["/formatb"].stateValues.value).eq("latex"); + expect(stateVariables["/formatc"].stateValues.value).eq("latex"); + expect(stateVariables["/formatd"].stateValues.value).eq("text"); + + // change format of second back to text + await updateTextInputValue({ + componentName: "/ti2", + text: "text", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/a"].stateValues.latex)).eq("οΌΏ"); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "\\sin(u)οΌΏ", + ); + expect(stateVariables["/formata"].stateValues.value).eq("text"); + expect(stateVariables["/formatb"].stateValues.value).eq("text"); + expect(stateVariables["/formatc"].stateValues.value).eq("text"); + expect(stateVariables["/formatd"].stateValues.value).eq("text"); + + // change format of first back to latex + await updateTextInputValue({ + componentName: "/ti1", + text: "latex", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/a"].stateValues.latex)).eq( + "\\sin(x)\\sin(y)", + ); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "\\sin(u)\\sin(v)", + ); + expect(stateVariables["/formata"].stateValues.value).eq("latex"); + expect(stateVariables["/formatb"].stateValues.value).eq("text"); + expect(stateVariables["/formatc"].stateValues.value).eq("text"); + expect(stateVariables["/formatd"].stateValues.value).eq("latex"); + }); + + it("simplify math", async () => { + let core = await createTestCore({ + doenetML: ` +

Default is no simplification: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

+

Explicit no simplify: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

+

Full simplify a: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

+

Full simplify b: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

+

Simplify numbers: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

+

Simplify numbers preserve order: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "1x^{2}-3+0x^{2}+4-2x^{2}-3+5x^{2}", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "1x^{2}-3+0x^{2}+4-2x^{2}-3+5x^{2}", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "4x^{2}-2", + ); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq( + "4x^{2}-2", + ); + expect(cleanLatex(stateVariables["/m5"].stateValues.latex)).eq( + "-2x^{2}+x^{2}+5x^{2}-2", + ); + expect(cleanLatex(stateVariables["/m6"].stateValues.latex)).eq( + "x^{2}+1-2x^{2}-3+5x^{2}", + ); + + let originalTree = [ + "+", + ["*", 1, ["^", "x", 2]], + -3, + ["*", 0, ["^", "x", 2]], + 4, + ["-", ["*", 2, ["^", "x", 2]]], + -3, + ["*", 5, ["^", "x", 2]], + ]; + + expect(stateVariables["/m1"].stateValues.value.tree).eqls(originalTree); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(originalTree); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "+", + ["*", 4, ["^", "x", 2]], + -2, + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "+", + ["*", 4, ["^", "x", 2]], + -2, + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "+", + ["*", -2, ["^", "x", 2]], + ["^", "x", 2], + ["*", 5, ["^", "x", 2]], + -2, + ]); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "+", + ["^", "x", 2], + 1, + ["*", -2, ["^", "x", 2]], + -3, + ["*", 5, ["^", "x", 2]], + ]); + }); + + it("expand math", async () => { + let core = await createTestCore({ + doenetML: ` +

Default is to not expand: (x-3)(2x+4)

+

Expand: (x-3)(2x+4)

+

Don't expand sum: (x-3)(2x+4) - (3x+5)(7-x)

+

Expand: (x-3)(2x+4) - (3x+5)(7-x)

+

Expand: 2(1-x)(1+x)(-2)

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "(x-3)(2x+4)", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "2x^{2}-2x-12", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "(x-3)(2x+4)-(3x+5)(7-x)", + ); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq( + "5x^{2}-18x-47", + ); + expect(cleanLatex(stateVariables["/m5"].stateValues.latex)).eq( + "4x^{2}-4", + ); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "*", + ["+", "x", -3], + ["+", ["*", 2, "x"], 4], + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + ["*", 2, ["^", "x", 2]], + ["*", -2, "x"], + -12, + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "+", + ["*", ["+", "x", -3], ["+", ["*", 2, "x"], 4]], + ["-", ["*", ["+", ["*", 3, "x"], 5], ["+", 7, ["-", "x"]]]], + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "+", + ["*", 5, ["^", "x", 2]], + ["*", -18, "x"], + -47, + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "+", + ["*", 4, ["^", "x", 2]], + -4, + ]); + }); + + it("create vectors and intervals", async () => { + let core = await createTestCore({ + doenetML: ` +

Default: (1,2,3),(4,5),[6,7],(8,9],[10,11)

+

Create vectors: (1,2,3),(4,5),[6,7],(8,9],[10,11)

+

Create intervals: (1,2,3),(4,5),[6,7],(8,9],[10,11)

+

Create vectors and intervals: (1,2,3),(4,5),[6,7],(8,9],[10,11)

+

Alt vectors: ⟨1,2,3⟩,⟨4,5⟩,[6,7],(8,9],[10,11)

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "(1,2,3),(4,5),[6,7],(8,9],[10,11)", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "(1,2,3),(4,5),[6,7],(8,9],[10,11)", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "(1,2,3),(4,5),[6,7],(8,9],[10,11)", + ); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq( + "(1,2,3),(4,5),[6,7],(8,9],[10,11)", + ); + expect(cleanLatex(stateVariables["/m5"].stateValues.latex)).eq( + "\\langle1,2,3\\rangle,\\langle4,5\\rangle,[6,7],(8,9],[10,11)", + ); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "list", + ["tuple", 1, 2, 3], + ["tuple", 4, 5], + ["array", 6, 7], + ["interval", ["tuple", 8, 9], ["tuple", false, true]], + ["interval", ["tuple", 10, 11], ["tuple", true, false]], + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "list", + ["vector", 1, 2, 3], + ["vector", 4, 5], + ["array", 6, 7], + ["interval", ["tuple", 8, 9], ["tuple", false, true]], + ["interval", ["tuple", 10, 11], ["tuple", true, false]], + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "list", + ["tuple", 1, 2, 3], + ["interval", ["tuple", 4, 5], ["tuple", false, false]], + ["interval", ["tuple", 6, 7], ["tuple", true, true]], + ["interval", ["tuple", 8, 9], ["tuple", false, true]], + ["interval", ["tuple", 10, 11], ["tuple", true, false]], + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "list", + ["vector", 1, 2, 3], + ["vector", 4, 5], + ["interval", ["tuple", 6, 7], ["tuple", true, true]], + ["interval", ["tuple", 8, 9], ["tuple", false, true]], + ["interval", ["tuple", 10, 11], ["tuple", true, false]], + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "list", + ["altvector", 1, 2, 3], + ["altvector", 4, 5], + ["array", 6, 7], + ["interval", ["tuple", 8, 9], ["tuple", false, true]], + ["interval", ["tuple", 10, 11], ["tuple", true, false]], + ]); + }); + + it("display small numbers as zero by default", async () => { + let core = await createTestCore({ + doenetML: ` +

2x + (1E-15)y

+

2x + (1E-15)y

+

2x + (1E-13)y

+

2x + (1E-13)y

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "2x+1\\cdot10^{-15}y", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq("2x+0y"); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "2x+1\\cdot10^{-13}y", + ); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq("2x+0y"); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + ["*", 1e-15, "y"], + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + ["*", 1e-15, "y"], + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + ["*", 1e-13, "y"], + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + ["*", 1e-13, "y"], + ]); + expect(stateVariables["/m1"].stateValues.displaySmallAsZero).eq(0); + expect(stateVariables["/m2"].stateValues.displaySmallAsZero).eq(1e-14); + expect(stateVariables["/m3"].stateValues.displaySmallAsZero).eq(1e-14); + expect(stateVariables["/m4"].stateValues.displaySmallAsZero).eq(1e-12); + }); + + it("display digits and decimals", async () => { + let core = await createTestCore({ + doenetML: ` +

621802.3520303639164826281

+

31.3835205397397634 x + 4pi

+

621802.3520303639164826281

+

31.3835205397397634 x + 4pi

+

621802.3520303639164826281

+

31.3835205397397634 x + 4pi

+

$expr1{name="expr1Dig5a" displayDigits="5"}

+

$expr2{name="expr2Dig5a" displayDigits="5"}

+

$expr1{name="expr1Dec5a" displayDecimals="5"}

+

$expr2{name="expr2Dec5a" displayDecimals="5"}

+

$expr1Dec5{name="expr1Dig5b" displayDigits="5"}

+

$expr2Dec5{name="expr2Dig5b" displayDigits="5"}

+

$expr1Dig5{name="expr1Dec5b" displayDecimals="5"}

+

$expr2Dig5{name="expr2Dec5b" displayDecimals="5"}

+

$expr1Dec5a{name="expr1Dig5c" displayDigits="5"}

+

$expr2Dec5a{name="expr2Dig5c" displayDigits="5"}

+

$expr1Dig5a{name="expr1Dec5c" displayDecimals="5"}

+

$expr2Dig5a{name="expr2Dec5c" displayDecimals="5"}

+

$expr1Dec5b{name="expr1Dig5d" displayDigits="5"}

+

$expr2Dec5b{name="expr2Dig5d" displayDigits="5"}

+

$expr1Dig5b{name="expr1Dec5d" displayDecimals="5"}

+

$expr2Dig5b{name="expr2Dec5d" displayDecimals="5"}

+ +

$expr1{name="expr1Dig5Dec1" displayDigits="5" displayDecimals="1"}

+

$expr2{name="expr2Dig5Dec1" displayDigits="5" displayDecimals="1"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/expr1"].stateValues.latex)).eq( + "621802.35", + ); + expect(cleanLatex(stateVariables["/expr2"].stateValues.latex)).eq( + "31.38x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dig5"].stateValues.latex)).eq( + "621800", + ); + expect(cleanLatex(stateVariables["/expr2Dig5"].stateValues.latex)).eq( + "31.384x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dec5"].stateValues.latex)).eq( + "621802.35203", + ); + expect(cleanLatex(stateVariables["/expr2Dec5"].stateValues.latex)).eq( + "31.38352x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dig5a"].stateValues.latex)).eq( + "621800", + ); + expect(cleanLatex(stateVariables["/expr2Dig5a"].stateValues.latex)).eq( + "31.384x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dec5a"].stateValues.latex)).eq( + "621802.35203", + ); + expect(cleanLatex(stateVariables["/expr2Dec5a"].stateValues.latex)).eq( + "31.38352x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dig5b"].stateValues.latex)).eq( + "621800", + ); + expect(cleanLatex(stateVariables["/expr2Dig5b"].stateValues.latex)).eq( + "31.384x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr2Dec5b"].stateValues.latex)).eq( + "31.38352x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dig5c"].stateValues.latex)).eq( + "621800", + ); + expect(cleanLatex(stateVariables["/expr2Dig5c"].stateValues.latex)).eq( + "31.384x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dec5c"].stateValues.latex)).eq( + "621802.35203", + ); + expect(cleanLatex(stateVariables["/expr2Dec5c"].stateValues.latex)).eq( + "31.38352x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dig5d"].stateValues.latex)).eq( + "621800", + ); + expect(cleanLatex(stateVariables["/expr2Dig5d"].stateValues.latex)).eq( + "31.384x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dec5d"].stateValues.latex)).eq( + "621802.35203", + ); + expect(cleanLatex(stateVariables["/expr2Dec5d"].stateValues.latex)).eq( + "31.38352x+4\\pi", + ); + expect( + cleanLatex(stateVariables["/expr1Dig5Dec1"].stateValues.latex), + ).eq("621802.4"); + expect( + cleanLatex(stateVariables["/expr2Dig5Dec1"].stateValues.latex), + ).eq("31.384x+4\\pi"); + + expect(stateVariables["/expr1"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig5"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig5"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec5"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec5"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig5a"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig5a"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec5a"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec5a"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig5b"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig5b"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec5b"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec5b"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig5c"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig5c"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec5c"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec5c"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig5d"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig5d"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec5d"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec5d"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig5Dec1"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig5Dec1"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + + expect(stateVariables["/expr1"].stateValues.valueForDisplay.tree).eq( + 621802.35, + ); + expect(stateVariables["/expr2"].stateValues.valueForDisplay.tree).eqls([ + "+", + ["*", 31.38, "x"], + ["*", 4, "pi"], + ]); + expect( + stateVariables["/expr1Dig5"].stateValues.valueForDisplay.tree, + ).eq(621800); + expect( + stateVariables["/expr2Dig5"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec5"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dec5"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig5a"].stateValues.valueForDisplay.tree, + ).eq(621800); + expect( + stateVariables["/expr2Dig5a"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec5a"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dec5a"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig5b"].stateValues.valueForDisplay.tree, + ).eq(621800); + expect( + stateVariables["/expr2Dig5b"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec5b"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dec5b"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig5c"].stateValues.valueForDisplay.tree, + ).eq(621800); + expect( + stateVariables["/expr2Dig5c"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec5c"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dec5c"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig5d"].stateValues.valueForDisplay.tree, + ).eq(621800); + expect( + stateVariables["/expr2Dig5d"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec5d"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dec5d"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig5Dec1"].stateValues.valueForDisplay.tree, + ).eq(621802.4); + expect( + stateVariables["/expr2Dig5Dec1"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); + }); + + it("display digits and decimals 2", async () => { + let core = await createTestCore({ + doenetML: ` +

621802.3520303639164826281

+

31.3835205397397634 x + 4pi

+

621802.3520303639164826281

+

31.3835205397397634 x + 4pi

+

621802.3520303639164826281

+

31.3835205397397634 x + 4pi

+

$expr1{name="expr1Dig5a" displayDigits="5"}

+

$expr2{name="expr2Dig5a" displayDigits="5"}

+

$expr1{name="expr1Dec5a" displayDecimals="5"}

+

$expr2{name="expr2Dec5a" displayDecimals="5"}

+

$expr1Dec5{name="expr1Dig8Dec5" displayDigits="8" displayDecimals="5"}

+

$expr2Dec5{name="expr2Dig8Dec5" displayDigits="8" displayDecimals="5"}

+

$expr1Dig5{name="expr1Dec8Dig5" displayDigits="5" displayDecimals="8"}

+

$expr2Dig5{name="expr2Dec8Dig5" displayDigits="5" displayDecimals="8"}

+

$expr1Dec5a{name="expr1Dig8Dec5a" displayDigits="8" displayDecimals="5"}

+

$expr2Dec5a{name="expr2Dig8Dec5a" displayDigits="8" displayDecimals="5"}

+

$expr1Dig5a{name="expr1Dec8Dig5a" displayDigits="5" displayDecimals="8"}

+

$expr2Dig5a{name="expr2Dec8Dig5a" displayDigits="5" displayDecimals="8"}

+

$expr1Dec8Dig5{name="expr1Dig3Dec8" displayDigits="3" displayDecimals="8"}

+

$expr2Dec8Dig5{name="expr2Dig3Dec8" displayDigits="3" displayDecimals="8"}

+

$expr1Dig8Dec5{name="expr1Dec3Dig8" displayDigits="8" displayDecimals="3"}

+

$expr2Dig8Dec5{name="expr2Dec3Dig8" displayDigits="8" displayDecimals="3"}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/expr1"].stateValues.latex)).eq( + "621802.35", + ); + expect(cleanLatex(stateVariables["/expr2"].stateValues.latex)).eq( + "31.38x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dig5"].stateValues.latex)).eq( + "621800", + ); + expect(cleanLatex(stateVariables["/expr2Dig5"].stateValues.latex)).eq( + "31.384x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dec5"].stateValues.latex)).eq( + "621802.35203", + ); + expect(cleanLatex(stateVariables["/expr2Dec5"].stateValues.latex)).eq( + "31.38352x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dig5a"].stateValues.latex)).eq( + "621800", + ); + expect(cleanLatex(stateVariables["/expr2Dig5a"].stateValues.latex)).eq( + "31.384x+4\\pi", + ); + expect(cleanLatex(stateVariables["/expr1Dec5a"].stateValues.latex)).eq( + "621802.35203", + ); + expect(cleanLatex(stateVariables["/expr2Dec5a"].stateValues.latex)).eq( + "31.38352x+4\\pi", + ); + expect( + cleanLatex(stateVariables["/expr1Dig8Dec5"].stateValues.latex), + ).eq("621802.35203"); + expect( + cleanLatex(stateVariables["/expr2Dig8Dec5"].stateValues.latex), + ).eq("31.383521x+4\\pi"); + expect( + cleanLatex(stateVariables["/expr1Dec8Dig5"].stateValues.latex), + ).eq("621802.35203036"); + expect( + cleanLatex(stateVariables["/expr2Dec8Dig5"].stateValues.latex), + ).eq("31.38352054x+4\\pi"); + expect( + cleanLatex(stateVariables["/expr1Dig8Dec5a"].stateValues.latex), + ).eq("621802.35203"); + expect( + cleanLatex(stateVariables["/expr2Dig8Dec5a"].stateValues.latex), + ).eq("31.383521x+4\\pi"); + expect( + cleanLatex(stateVariables["/expr1Dec8Dig5a"].stateValues.latex), + ).eq("621802.35203036"); + expect( + cleanLatex(stateVariables["/expr2Dec8Dig5a"].stateValues.latex), + ).eq("31.38352054x+4\\pi"); + expect( + cleanLatex(stateVariables["/expr1Dig3Dec8"].stateValues.latex), + ).eq("621802.35203036"); + expect( + cleanLatex(stateVariables["/expr2Dig3Dec8"].stateValues.latex), + ).eq("31.38352054x+4\\pi"); + expect( + cleanLatex(stateVariables["/expr1Dec3Dig8"].stateValues.latex), + ).eq("621802.352"); + expect( + cleanLatex(stateVariables["/expr2Dec3Dig8"].stateValues.latex), + ).eq("31.383521x+4\\pi"); + + expect(stateVariables["/expr1"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig5"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig5"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec5"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec5"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig5a"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig5a"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec5a"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec5a"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig8Dec5"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig8Dec5"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec8Dig5"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec8Dig5"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig8Dec5a"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig8Dec5a"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec8Dig5a"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec8Dig5a"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dig3Dec8"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dig3Dec8"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + expect(stateVariables["/expr1Dec3Dig8"].stateValues.value.tree).eq( + 621802.3520303639, + ); + expect(stateVariables["/expr2Dec3Dig8"].stateValues.value.tree).eqls([ + "+", + ["*", 31.383520539739763, "x"], + ["*", 4, "pi"], + ]); + + expect(stateVariables["/expr1"].stateValues.valueForDisplay.tree).eq( + 621802.35, + ); + expect(stateVariables["/expr2"].stateValues.valueForDisplay.tree).eqls([ + "+", + ["*", 31.38, "x"], + ["*", 4, "pi"], + ]); + expect( + stateVariables["/expr1Dig5"].stateValues.valueForDisplay.tree, + ).eq(621800); + expect( + stateVariables["/expr2Dig5"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec5"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dec5"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig5a"].stateValues.valueForDisplay.tree, + ).eq(621800); + expect( + stateVariables["/expr2Dig5a"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec5a"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dec5a"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig8Dec5"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dig8Dec5"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.383521, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec8Dig5"].stateValues.valueForDisplay.tree, + ).eq(621802.35203036); + expect( + stateVariables["/expr2Dec8Dig5"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352054, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig8Dec5a"].stateValues.valueForDisplay.tree, + ).eq(621802.35203); + expect( + stateVariables["/expr2Dig8Dec5a"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.383521, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec8Dig5a"].stateValues.valueForDisplay.tree, + ).eq(621802.35203036); + expect( + stateVariables["/expr2Dec8Dig5a"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352054, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dig3Dec8"].stateValues.valueForDisplay.tree, + ).eq(621802.35203036); + expect( + stateVariables["/expr2Dig3Dec8"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.38352054, "x"], ["*", 4, "pi"]]); + expect( + stateVariables["/expr1Dec3Dig8"].stateValues.valueForDisplay.tree, + ).eq(621802.352); + expect( + stateVariables["/expr2Dec3Dig8"].stateValues.valueForDisplay.tree, + ).eqls(["+", ["*", 31.383521, "x"], ["*", 4, "pi"]]); + }); + + it("pad zeros with display digits and decimals", async () => { + let core = await createTestCore({ + doenetML: ` +

62.1

+

162.1*10^(-3)

+

1.3 x + 4pi

+

$m1{name="dig5a" displayDigits="5"}

+

$m1{name="dig5apad" displayDigits="5" padZeros}

+

$m2{name="dig5b" displayDigits="5"}

+

$m2{name="dig5bpad" displayDigits="5" padZeros}

+

$m3{name="dig5c" displayDigits="5"}

+

$m3{name="dig5cpad" displayDigits="5" padZeros}

+

$m1{name="dec5a" displayDecimals="5"}

+

$m1{name="dec5apad" displayDecimals="5" padZeros}

+

$m2{name="dec5b" displayDecimals="5"}

+

$m2{name="dec5bpad" displayDecimals="5" padZeros}

+

$m3{name="dec5c" displayDecimals="5"}

+

$m3{name="dec5cpad" displayDecimals="5" padZeros}

+

$m1{name="dig5dec1a" displayDigits="5" displayDecimals="1"}

+

$m1{name="dig5dec1apad" displayDigits="5" displayDecimals="1" padZeros}

+

$m2{name="dig5dec1b" displayDigits="5" displayDecimals="1"}

+

$m2{name="dig5dec1bpad" displayDigits="5" displayDecimals="1" padZeros}

+

$m3{name="dig5dec1c" displayDigits="5" displayDecimals="1"}

+

$m3{name="dig5dec1cpad" displayDigits="5" displayDecimals="1" padZeros}

+ +

$dig5a.text{assignNames="dig5aText"}

+

$dig5apad.text{assignNames="dig5apadText"}

+

$dig5b.text{assignNames="dig5bText"}

+

$dig5bpad.text{assignNames="dig5bpadText"}

+

$dig5c.text{assignNames="dig5cText"}

+

$dig5cpad.text{assignNames="dig5cpadText"}

+

$dec5a.text{assignNames="dec5aText"}

+

$dec5apad.text{assignNames="dec5apadText"}

+

$dec5b.text{assignNames="dec5bText"}

+

$dec5bpad.text{assignNames="dec5bpadText"}

+

$dec5c.text{assignNames="dec5cText"}

+

$dec5cpad.text{assignNames="dec5cpadText"}

+

$dig5dec1a.text{assignNames="dig5dec1aText"}

+

$dig5dec1apad.text{assignNames="dig5dec1apadText"}

+

$dig5dec1b.text{assignNames="dig5dec1bText"}

+

$dig5dec1bpad.text{assignNames="dig5dec1bpadText"}

+

$dig5dec1c.text{assignNames="dig5dec1cText"}

+

$dig5dec1cpad.text{assignNames="dig5dec1cpadText"}

+ +

$dig5a.value{assignNames="dig5aValue"}

+

$dig5apad.value{assignNames="dig5apadValue"}

+

$dig5b.value{assignNames="dig5bValue"}

+

$dig5bpad.value{assignNames="dig5bpadValue"}

+

$dig5c.value{assignNames="dig5cValue"}

+

$dig5cpad.value{assignNames="dig5cpadValue"}

+

$dec5a.value{assignNames="dec5aValue"}

+

$dec5apad.value{assignNames="dec5apadValue"}

+

$dec5b.value{assignNames="dec5bValue"}

+

$dec5bpad.value{assignNames="dec5bpadValue"}

+

$dec5c.value{assignNames="dec5cValue"}

+

$dec5cpad.value{assignNames="dec5cpadValue"}

+

$dig5dec1a.value{assignNames="dig5dec1aValue"}

+

$dig5dec1apad.value{assignNames="dig5dec1apadValue"}

+

$dig5dec1b.value{assignNames="dig5dec1bValue"}

+

$dig5dec1bpad.value{assignNames="dig5dec1bpadValue"}

+

$dig5dec1c.value{assignNames="dig5dec1cValue"}

+

$dig5dec1cpad.value{assignNames="dig5dec1cpadValue"}

+ +

$dig5a.number{assignNames="dig5aNumber"}

+

$dig5apad.number{assignNames="dig5apadNumber"}

+

$dig5b.number{assignNames="dig5bNumber"}

+

$dig5bpad.number{assignNames="dig5bpadNumber"}

+

$dig5c.number{assignNames="dig5cNumber"}

+

$dig5cpad.number{assignNames="dig5cpadNumber"}

+

$dec5a.number{assignNames="dec5aNumber"}

+

$dec5apad.number{assignNames="dec5apadNumber"}

+

$dec5b.number{assignNames="dec5bNumber"}

+

$dec5bpad.number{assignNames="dec5bpadNumber"}

+

$dec5c.number{assignNames="dec5cNumber"}

+

$dec5cpad.number{assignNames="dec5cpadNumber"}

+

$dig5dec1a.number{assignNames="dig5dec1aNumber"}

+

$dig5dec1apad.number{assignNames="dig5dec1apadNumber"}

+

$dig5dec1b.number{assignNames="dig5dec1bNumber"}

+

$dig5dec1bpad.number{assignNames="dig5dec1bpadNumber"}

+

$dig5dec1c.number{assignNames="dig5dec1cNumber"}

+

$dig5dec1cpad.number{assignNames="dig5dec1cpadNumber"}

+ +

$dig5a

+

$dig5apad

+

$dig5b

+

$dig5bpad

+

$dig5c

+

$dig5cpad

+

$dec5a

+

$dec5apad

+

$dec5b

+

$dec5bpad

+

$dec5c

+

$dec5cpad

+

$dig5dec1a

+

$dig5dec1apad

+

$dig5dec1b

+

$dig5dec1bpad

+

$dig5dec1c

+

$dig5dec1cpad

+ +

$dig5a

+

$dig5apad

+

$dig5b

+

$dig5bpad

+

$dig5c

+

$dig5cpad

+

$dec5a

+

$dec5apad

+

$dec5b

+

$dec5bpad

+

$dec5c

+

$dec5cpad

+

$dig5dec1a

+

$dig5dec1apad

+

$dig5dec1b

+

$dig5dec1bpad

+

$dig5dec1c

+

$dig5dec1cpad

+ +

$dig5a.x1{assignNames="dig5aX1"}

+

$dig5apad.x1{assignNames="dig5apadX1"}

+

$dig5b.x1{assignNames="dig5bX1"}

+

$dig5bpad.x1{assignNames="dig5bpadX1"}

+

$dig5c.x1{assignNames="dig5cX1"}

+

$dig5cpad.x1{assignNames="dig5cpadX1"}

+

$dec5a.x1{assignNames="dec5aX1"}

+

$dec5apad.x1{assignNames="dec5apadX1"}

+

$dec5b.x1{assignNames="dec5bX1"}

+

$dec5bpad.x1{assignNames="dec5bpadX1"}

+

$dec5c.x1{assignNames="dec5cX1"}

+

$dec5cpad.x1{assignNames="dec5cpadX1"}

+

$dig5dec1a.x1{assignNames="dig5dec1aX1"}

+

$dig5dec1apad.x1{assignNames="dig5dec1apadX1"}

+

$dig5dec1b.x1{assignNames="dig5dec1bX1"}

+

$dig5dec1bpad.x1{assignNames="dig5dec1bpadX1"}

+

$dig5dec1c.x1{assignNames="dig5dec1cX1"}

+

$dig5dec1cpad.x1{assignNames="dig5dec1cpadX1"}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq("62.1"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect(cleanLatex(stateVariables["/dig5a"].stateValues.latex)).eq( + "62.1", + ); + expect(cleanLatex(stateVariables["/dig5apad"].stateValues.latex)).eq( + "62.100", + ); + expect(cleanLatex(stateVariables["/dig5b"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/dig5bpad"].stateValues.latex)).eq( + "162.10\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/dig5c"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect(cleanLatex(stateVariables["/dig5cpad"].stateValues.latex)).eq( + "1.3000x+4.0000\\pi", + ); + expect(cleanLatex(stateVariables["/dec5a"].stateValues.latex)).eq( + "62.1", + ); + expect(cleanLatex(stateVariables["/dec5apad"].stateValues.latex)).eq( + "62.10000", + ); + expect(cleanLatex(stateVariables["/dec5b"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/dec5bpad"].stateValues.latex)).eq( + "162.10000\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/dec5c"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect(cleanLatex(stateVariables["/dec5cpad"].stateValues.latex)).eq( + "1.30000x+4.00000\\pi", + ); + expect(cleanLatex(stateVariables["/dig5dec1a"].stateValues.latex)).eq( + "62.1", + ); + expect( + cleanLatex(stateVariables["/dig5dec1apad"].stateValues.latex), + ).eq("62.100"); + expect(cleanLatex(stateVariables["/dig5dec1b"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect( + cleanLatex(stateVariables["/dig5dec1bpad"].stateValues.latex), + ).eq("162.10\\cdot10^{-3}"); + expect(cleanLatex(stateVariables["/dig5dec1c"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect( + cleanLatex(stateVariables["/dig5dec1cpad"].stateValues.latex), + ).eq("1.3000x+4.0000\\pi"); + + expect(stateVariables["/dig5aText"].stateValues.value).eq("62.1"); + expect(stateVariables["/dig5apadText"].stateValues.value).eq("62.100"); + expect(stateVariables["/dig5bText"].stateValues.value).eq( + "162.1 * 10⁻³", + ); + expect(stateVariables["/dig5bpadText"].stateValues.value).eq( + "162.10 * 10⁻³", + ); + expect(stateVariables["/dig5cText"].stateValues.value).eq( + "1.3 x + 4 Ο€", + ); + expect(stateVariables["/dig5cpadText"].stateValues.value).eq( + "1.3000 x + 4.0000 Ο€", + ); + expect(stateVariables["/dec5aText"].stateValues.value).eq("62.1"); + expect(stateVariables["/dec5apadText"].stateValues.value).eq( + "62.10000", + ); + expect(stateVariables["/dec5bText"].stateValues.value).eq( + "162.1 * 10⁻³", + ); + expect(stateVariables["/dec5bpadText"].stateValues.value).eq( + "162.10000 * 10⁻³", + ); + expect(stateVariables["/dec5cText"].stateValues.value).eq( + "1.3 x + 4 Ο€", + ); + expect(stateVariables["/dec5cpadText"].stateValues.value).eq( + "1.30000 x + 4.00000 Ο€", + ); + expect(stateVariables["/dig5dec1aText"].stateValues.value).eq("62.1"); + expect(stateVariables["/dig5dec1apadText"].stateValues.value).eq( + "62.100", + ); + expect(stateVariables["/dig5dec1bText"].stateValues.value).eq( + "162.1 * 10⁻³", + ); + expect(stateVariables["/dig5dec1bpadText"].stateValues.value).eq( + "162.10 * 10⁻³", + ); + expect(stateVariables["/dig5dec1cText"].stateValues.value).eq( + "1.3 x + 4 Ο€", + ); + expect(stateVariables["/dig5dec1cpadText"].stateValues.value).eq( + "1.3000 x + 4.0000 Ο€", + ); + expect(cleanLatex(stateVariables["/dig5aValue"].stateValues.latex)).eq( + "62.1", + ); + expect( + cleanLatex(stateVariables["/dig5apadValue"].stateValues.latex), + ).eq("62.100"); + expect(cleanLatex(stateVariables["/dig5bValue"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect( + cleanLatex(stateVariables["/dig5bpadValue"].stateValues.latex), + ).eq("162.10\\cdot10^{-3}"); + expect(cleanLatex(stateVariables["/dig5cValue"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect( + cleanLatex(stateVariables["/dig5cpadValue"].stateValues.latex), + ).eq("1.3000x+4.0000\\pi"); + expect(cleanLatex(stateVariables["/dec5aValue"].stateValues.latex)).eq( + "62.1", + ); + expect( + cleanLatex(stateVariables["/dec5apadValue"].stateValues.latex), + ).eq("62.10000"); + expect(cleanLatex(stateVariables["/dec5bValue"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect( + cleanLatex(stateVariables["/dec5bpadValue"].stateValues.latex), + ).eq("162.10000\\cdot10^{-3}"); + expect(cleanLatex(stateVariables["/dec5cValue"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect( + cleanLatex(stateVariables["/dec5cpadValue"].stateValues.latex), + ).eq("1.30000x+4.00000\\pi"); + expect( + cleanLatex(stateVariables["/dig5dec1aValue"].stateValues.latex), + ).eq("62.1"); + expect( + cleanLatex(stateVariables["/dig5dec1apadValue"].stateValues.latex), + ).eq("62.100"); + expect( + cleanLatex(stateVariables["/dig5dec1bValue"].stateValues.latex), + ).eq("162.1\\cdot10^{-3}"); + expect( + cleanLatex(stateVariables["/dig5dec1bpadValue"].stateValues.latex), + ).eq("162.10\\cdot10^{-3}"); + expect( + cleanLatex(stateVariables["/dig5dec1cValue"].stateValues.latex), + ).eq("1.3x+4\\pi"); + expect( + cleanLatex(stateVariables["/dig5dec1cpadValue"].stateValues.latex), + ).eq("1.3000x+4.0000\\pi"); + + expect(stateVariables["/dig5aNumber"].stateValues.text).eq("62.1"); + expect(stateVariables["/dig5apadNumber"].stateValues.text).eq("62.100"); + expect(stateVariables["/dig5bNumber"].stateValues.text).eq("0.1621"); + expect(stateVariables["/dig5bpadNumber"].stateValues.text).eq( + "0.16210", + ); + expect(stateVariables["/dig5cNumber"].stateValues.text).eq("NaN"); + expect(stateVariables["/dig5cpadNumber"].stateValues.text).eq("NaN"); + expect(stateVariables["/dec5aNumber"].stateValues.text).eq("62.1"); + expect(stateVariables["/dec5apadNumber"].stateValues.text).eq( + "62.10000", + ); + expect(stateVariables["/dec5bNumber"].stateValues.text).eq("0.1621"); + expect(stateVariables["/dec5bpadNumber"].stateValues.text).eq( + "0.16210", + ); + expect(stateVariables["/dec5cNumber"].stateValues.text).eq("NaN"); + expect(stateVariables["/dec5cpadNumber"].stateValues.text).eq("NaN"); + expect(stateVariables["/dig5dec1aNumber"].stateValues.text).eq("62.1"); + expect(stateVariables["/dig5dec1apadNumber"].stateValues.text).eq( + "62.100", + ); + expect(stateVariables["/dig5dec1bNumber"].stateValues.text).eq( + "0.1621", + ); + expect(stateVariables["/dig5dec1bpadNumber"].stateValues.text).eq( + "0.16210", + ); + expect(stateVariables["/dig5dec1cNumber"].stateValues.text).eq("NaN"); + expect(stateVariables["/dig5dec1cpadNumber"].stateValues.text).eq( + "NaN", + ); + + expect(cleanLatex(stateVariables["/dig5aMath"].stateValues.latex)).eq( + "62.1", + ); + expect( + cleanLatex(stateVariables["/dig5apadMath"].stateValues.latex), + ).eq("62.100"); + expect(cleanLatex(stateVariables["/dig5bMath"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect( + cleanLatex(stateVariables["/dig5bpadMath"].stateValues.latex), + ).eq("162.10\\cdot10^{-3}"); + expect(cleanLatex(stateVariables["/dig5cMath"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect( + cleanLatex(stateVariables["/dig5cpadMath"].stateValues.latex), + ).eq("1.3000x+4.0000\\pi"); + expect(cleanLatex(stateVariables["/dec5aMath"].stateValues.latex)).eq( + "62.1", + ); + expect( + cleanLatex(stateVariables["/dec5apadMath"].stateValues.latex), + ).eq("62.10000"); + expect(cleanLatex(stateVariables["/dec5bMath"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect( + cleanLatex(stateVariables["/dec5bpadMath"].stateValues.latex), + ).eq("162.10000\\cdot10^{-3}"); + expect(cleanLatex(stateVariables["/dec5cMath"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect( + cleanLatex(stateVariables["/dec5cpadMath"].stateValues.latex), + ).eq("1.30000x+4.00000\\pi"); + expect( + cleanLatex(stateVariables["/dig5dec1aMath"].stateValues.latex), + ).eq("62.1"); + expect( + cleanLatex(stateVariables["/dig5dec1apadMath"].stateValues.latex), + ).eq("62.100"); + expect( + cleanLatex(stateVariables["/dig5dec1bMath"].stateValues.latex), + ).eq("162.1\\cdot10^{-3}"); + expect( + cleanLatex(stateVariables["/dig5dec1bpadMath"].stateValues.latex), + ).eq("162.10\\cdot10^{-3}"); + expect( + cleanLatex(stateVariables["/dig5dec1cMath"].stateValues.latex), + ).eq("1.3x+4\\pi"); + expect( + cleanLatex(stateVariables["/dig5dec1cpadMath"].stateValues.latex), + ).eq("1.3000x+4.0000\\pi"); + + expect(stateVariables["/dig5aNumber2"].stateValues.text).eq("62.1"); + expect(stateVariables["/dig5apadNumber2"].stateValues.text).eq( + "62.100", + ); + expect(stateVariables["/dig5bNumber2"].stateValues.text).eq("0.1621"); + expect(stateVariables["/dig5bpadNumber2"].stateValues.text).eq( + "0.16210", + ); + expect(stateVariables["/dig5cNumber2"].stateValues.text).eq("NaN"); + expect(stateVariables["/dig5cpadNumber2"].stateValues.text).eq("NaN"); + expect(stateVariables["/dec5aNumber2"].stateValues.text).eq("62.1"); + expect(stateVariables["/dec5apadNumber2"].stateValues.text).eq( + "62.10000", + ); + expect(stateVariables["/dec5bNumber2"].stateValues.text).eq("0.1621"); + expect(stateVariables["/dec5bpadNumber2"].stateValues.text).eq( + "0.16210", + ); + expect(stateVariables["/dec5cNumber2"].stateValues.text).eq("NaN"); + expect(stateVariables["/dec5cpadNumber2"].stateValues.text).eq("NaN"); + expect(stateVariables["/dig5dec1aNumber2"].stateValues.text).eq("62.1"); + expect(stateVariables["/dig5dec1apadNumber2"].stateValues.text).eq( + "62.100", + ); + expect(stateVariables["/dig5dec1bNumber2"].stateValues.text).eq( + "0.1621", + ); + expect(stateVariables["/dig5dec1bpadNumber2"].stateValues.text).eq( + "0.16210", + ); + expect(stateVariables["/dig5dec1cNumber2"].stateValues.text).eq("NaN"); + expect(stateVariables["/dig5dec1cpadNumber2"].stateValues.text).eq( + "NaN", + ); + + expect(cleanLatex(stateVariables["/dig5aX1"].stateValues.latex)).eq( + "62.1", + ); + expect(cleanLatex(stateVariables["/dig5apadX1"].stateValues.latex)).eq( + "62.100", + ); + expect(cleanLatex(stateVariables["/dig5bX1"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/dig5bpadX1"].stateValues.latex)).eq( + "162.10\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/dig5cX1"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect(cleanLatex(stateVariables["/dig5cpadX1"].stateValues.latex)).eq( + "1.3000x+4.0000\\pi", + ); + expect(cleanLatex(stateVariables["/dec5aX1"].stateValues.latex)).eq( + "62.1", + ); + expect(cleanLatex(stateVariables["/dec5apadX1"].stateValues.latex)).eq( + "62.10000", + ); + expect(cleanLatex(stateVariables["/dec5bX1"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/dec5bpadX1"].stateValues.latex)).eq( + "162.10000\\cdot10^{-3}", + ); + expect(cleanLatex(stateVariables["/dec5cX1"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect(cleanLatex(stateVariables["/dec5cpadX1"].stateValues.latex)).eq( + "1.30000x+4.00000\\pi", + ); + expect(cleanLatex(stateVariables["/dig5dec1aX1"].stateValues.latex)).eq( + "62.1", + ); + expect( + cleanLatex(stateVariables["/dig5dec1apadX1"].stateValues.latex), + ).eq("62.100"); + expect(cleanLatex(stateVariables["/dig5dec1bX1"].stateValues.latex)).eq( + "162.1\\cdot10^{-3}", + ); + expect( + cleanLatex(stateVariables["/dig5dec1bpadX1"].stateValues.latex), + ).eq("162.10\\cdot10^{-3}"); + expect(cleanLatex(stateVariables["/dig5dec1cX1"].stateValues.latex)).eq( + "1.3x+4\\pi", + ); + expect( + cleanLatex(stateVariables["/dig5dec1cpadX1"].stateValues.latex), + ).eq("1.3000x+4.0000\\pi"); + }); + + it("dynamic rounding", async () => { + let core = await createTestCore({ + doenetML: ` +

Number: 35203423.02352343201

+

Number of digits:

+

Number of decimals:

+

$n{displayDigits='$nDigits' displayDecimals='$nDecimals' name="na"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/n"].stateValues.latex)).eq( + "35203423.02", + ); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "35203423.024", + ); + + // higher decimals + await updateMathInputValue({ + componentName: "/nDecimals", + latex: "5", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "35203423.02352", + ); + + // lower decimals + await updateMathInputValue({ + componentName: "/nDecimals", + latex: "-3", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "35203000", + ); + + // increase digits + await updateMathInputValue({ + componentName: "/nDigits", + latex: "12", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "35203423.0235", + ); + + // invalid nDigits, falls back to decimals + await updateMathInputValue({ + componentName: "/nDigits", + latex: "x", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "35203000", + ); + + // invalid both, no rounding + await updateMathInputValue({ + componentName: "/nDecimals", + latex: "y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "35203423.023523435", + ); + + // only invalid nDecimals, falls back to digits + await updateMathInputValue({ + componentName: "/nDigits", + latex: "1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "40000000", + ); + + // negative decimals past number magnitude + await updateMathInputValue({ + componentName: "/nDecimals", + latex: "-8", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "40000000", + ); + + // becomes zero with no digits + await updateMathInputValue({ + componentName: "/nDigits", + latex: "0", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq("0"); + + // get number back with less rounding + await updateMathInputValue({ + componentName: "/nDecimals", + latex: "-6", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/na"].stateValues.latex)).eq( + "35000000", + ); + }); + + it("function symbols", async () => { + let core = await createTestCore({ + doenetML: ` +

f(x)

+

g(t)

+

h(z)

+

f(x)

+

g(t)

+

h(z)

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "apply", + "f", + "x", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "apply", + "g", + "t", + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "*", + "h", + "z", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "*", + "f", + "x", + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "apply", + "g", + "t", + ]); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "apply", + "h", + "z", + ]); + }); + + it("copy and overwrite function symbols", async () => { + let core = await createTestCore({ + doenetML: ` + f(x)+m(x) + $m1{functionSymbols="m" name="m2"} + $m2{functionSymbols="m f" name="m3"} + + f(x)+m(x) + $m4{functionSymbols="m" name="m5"} + $m5{functionSymbols="f" name="m6"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + ["apply", "f", "x"], + ["*", "m", "x"], + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + ["*", "f", "x"], + ["apply", "m", "x"], + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "+", + ["apply", "f", "x"], + ["apply", "m", "x"], + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "+", + ["apply", "f", "x"], + ["apply", "m", "x"], + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "+", + ["*", "f", "x"], + ["apply", "m", "x"], + ]); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "+", + ["apply", "f", "x"], + ["*", "m", "x"], + ]); + }); + + it("sourcesAreFunctionSymbols", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ +

$f($x)

+

$x($f)

+

$f($x)

+

$x($f)

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let f = stateVariables["/f"].stateValues.value.tree; + let x = stateVariables["/x"].stateValues.value.tree; + + expect(stateVariables["/m1"].stateValues.value.tree).eqls(["*", f, x]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(["*", x, f]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "apply", + f, + x, + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls(["*", x, f]); + }); + + it("copy and overwrite sourcesAreFunctionSymbols", async () => { + let core = await createTestCore({ + doenetML: ` +

+ +

$f(x)

+

$m1{sourcesAreFunctionSymbols="f" name="m2"}

+

$m2{sourcesAreFunctionSymbols="" name="m3"}

+ +

$f(x)

+

$m4{sourcesAreFunctionSymbols="" name="m5"}

+

$m5{sourcesAreFunctionSymbols="f" name="m6"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let f = stateVariables["/f"].stateValues.value.tree; + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "*", + f, + "x", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "apply", + f, + "x", + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "*", + f, + "x", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "apply", + f, + "x", + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "*", + f, + "x", + ]); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "apply", + f, + "x", + ]); + }); + + it("copy and overwrite simplify", async () => { + let core = await createTestCore({ + doenetML: ` +

x+x

+

$m1{simplify name="m2"}

+

$m2{simplify="none" name="m3"}

+

$m1.value{simplify assignNames="m2a"}

+

$m2.value{simplify="none" assignNames="m3a"}

+ +

x+x

+

$m4{simplify="none" name="m5"}

+

$m5{simplify name="m6"}

+

$m4.value{simplify="none" assignNames="m5a"}

+

$m5a.value{simplify assignNames="m6a"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + ]); + expect(stateVariables["/m2a"].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables["/m3a"].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + ]); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables["/m5a"].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables["/m6a"].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + }); + + it("split symbols", async () => { + let core = await createTestCore({ + doenetML: ` +

xyz

+

xyz

+

xyz

+

xyx

+

xyx

+

xyx

+

xy_uv

+

x2_2x

+

2x_x2

+

xy uv x2y 2x x2

+

xy_uv

+

x2_2x

+

2x_x2

+

xy uv x2y 2x x2

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "*", + "y", + ["^", "x", 2], + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls("xyx"); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "*", + "y", + ["^", "x", 2], + ]); + expect(stateVariables["/m7"].stateValues.value.tree).eqls([ + "*", + "x", + ["_", "y", "u"], + "v", + ]); + expect(stateVariables["/m8"].stateValues.value.tree).eqls([ + "*", + ["_", "x2", 2], + "x", + ]); + expect(stateVariables["/m9"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x2"], + ]); + expect(stateVariables["/m10"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "u", + "v", + "x2y", + 2, + "x", + "x2", + ]); + expect(stateVariables["/m11"].stateValues.value.tree).eqls([ + "_", + "xy", + "uv", + ]); + expect(stateVariables["/m12"].stateValues.value.tree).eqls([ + "*", + ["_", "x2", 2], + "x", + ]); + expect(stateVariables["/m13"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x2"], + ]); + expect(stateVariables["/m14"].stateValues.value.tree).eqls([ + "*", + "xy", + "uv", + "x2y", + 2, + "x", + "x2", + ]); + }); + + it("split symbols, nested", async () => { + let core = await createTestCore({ + doenetML: ` +

xyz

+

xyz

+

xyz

+

xyx

+

xyx

+

xyx

+

xy_uv

+

x2_2x

+

2x_x2

+

xy uv x2y 2x x2

+

xy_uv

+

x2_2x

+

2x_x2

+

xy uv x2y 2x x2

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "*", + "y", + ["^", "x", 2], + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls("xyx"); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "*", + "y", + ["^", "x", 2], + ]); + expect(stateVariables["/m7"].stateValues.value.tree).eqls([ + "*", + "x", + ["_", "y", "u"], + "v", + ]); + expect(stateVariables["/m8"].stateValues.value.tree).eqls([ + "*", + ["_", "x2", 2], + "x", + ]); + expect(stateVariables["/m9"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x2"], + ]); + expect(stateVariables["/m10"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "u", + "v", + "x2y", + 2, + "x", + "x2", + ]); + expect(stateVariables["/m11"].stateValues.value.tree).eqls([ + "_", + "xy", + "uv", + ]); + expect(stateVariables["/m12"].stateValues.value.tree).eqls([ + "*", + ["_", "x2", 2], + "x", + ]); + expect(stateVariables["/m13"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x2"], + ]); + expect(stateVariables["/m14"].stateValues.value.tree).eqls([ + "*", + "xy", + "uv", + "x2y", + 2, + "x", + "x2", + ]); + }); + + it("split symbols, latex", async () => { + let core = await createTestCore({ + doenetML: ` +

xyz

+

xyz

+

\\operatorname{xyz}

+

\\operatorname{xyz}

+

xyz

+

xyx

+

xyx

+

\\operatorname{xyx}

+

\\operatorname{xyx}

+

xyx

+

xy_uv

+

x2_2x

+

\\operatorname{x2}_2x

+

2x_x2

+

2x_\\operatorname{x2}

+

2x_{x2}

+

xy uv x2y 2x x2

+

xy uv \\operatorname{x2y} 2x \\operatorname{x2}

+

xy_uv

+

\\operatorname{xy}_\\operatorname{uv}

+

\\operatorname{xy}_\\operatorname{uv}

+

x2_2x

+

\\operatorname{x2}_2x

+

2x_x2

+

2x_\\operatorname{x2}

+

xy uv x2y 2x x2

+

\\operatorname{xy} \\operatorname{uv} x2y 2x x2

+

\\operatorname{xy} \\operatorname{uv} x2y 2x x2

+

3^x2

+

3^x2

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/m2a"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/m2b"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "*", + "y", + ["^", "x", 2], + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls("xyx"); + expect(stateVariables["/m5a"].stateValues.value.tree).eqls("xyx"); + expect(stateVariables["/m5b"].stateValues.value.tree).eqls("xyx"); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "*", + "y", + ["^", "x", 2], + ]); + expect(stateVariables["/m7"].stateValues.value.tree).eqls([ + "*", + "x", + ["_", "y", "u"], + "v", + ]); + expect(stateVariables["/m8"].stateValues.value.tree).eqls([ + "*", + ["_", "x2", 2], + "x", + ]); + expect(stateVariables["/m8a"].stateValues.value.tree).eqls([ + "*", + ["_", "x2", 2], + "x", + ]); + expect(stateVariables["/m9"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x"], + 2, + ]); + expect(stateVariables["/m9a"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x2"], + ]); + expect(stateVariables["/m9b"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x2"], + ]); + expect(stateVariables["/m10"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "u", + "v", + "x2y", + 2, + "x", + "x2", + ]); + expect(stateVariables["/m10a"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "u", + "v", + "x2y", + 2, + "x", + "x2", + ]); + expect(stateVariables["/m11"].stateValues.value.tree).eqls([ + "_", + "xy", + "uv", + ]); + expect(stateVariables["/m11a"].stateValues.value.tree).eqls([ + "_", + "xy", + "uv", + ]); + expect(stateVariables["/m11b"].stateValues.value.tree).eqls([ + "_", + "xy", + "uv", + ]); + expect(stateVariables["/m12"].stateValues.value.tree).eqls([ + "*", + ["_", "x2", 2], + "x", + ]); + expect(stateVariables["/m12a"].stateValues.value.tree).eqls([ + "*", + ["_", "x2", 2], + "x", + ]); + expect(stateVariables["/m13"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x2"], + ]); + expect(stateVariables["/m13a"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", "x2"], + ]); + expect(stateVariables["/m14"].stateValues.value.tree).eqls([ + "*", + "xy", + "uv", + "x2y", + 2, + "x", + "x2", + ]); + expect(stateVariables["/m14a"].stateValues.value.tree).eqls([ + "*", + "xy", + "uv", + "x2y", + 2, + "x", + "x2", + ]); + expect(stateVariables["/m14b"].stateValues.value.tree).eqls([ + "*", + "xy", + "uv", + "x2y", + 2, + "x", + "x2", + ]); + expect(stateVariables["/m15"].stateValues.value.tree).eqls([ + "*", + ["^", 3, "x"], + 2, + ]); + expect(stateVariables["/m15a"].stateValues.value.tree).eqls([ + "^", + 3, + "x2", + ]); + }); + + it("copy and overwrite split symbols", async () => { + let core = await createTestCore({ + doenetML: ` +

xyz

+

$m1{splitSymbols="false" name="m2"}

+

$m2{splitSymbols name="m3"}

+ +

xyz

+

$m4{splitSymbols name="m5"}

+

$m5{splitSymbols="false" name="m6"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/m6"].stateValues.value.tree).eqls("xyz"); + }); + + it("merge lists with other containers", async () => { + let core = await createTestCore({ + doenetML: ` +

{a,b,c}

+ +

{a,b,c,d,e,f}

+

(a,b,c,d,e,f)

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/set"].stateValues.value.tree).eqls([ + "set", + "a", + "b", + "c", + ]); + // expect(stateVariables['/tuple'].stateValues.value.tree).eqls(["tuple", "a", "b", "c"]); + expect(stateVariables["/combinedSet"].stateValues.value.tree).eqls([ + "set", + "a", + "b", + "c", + "d", + "e", + "f", + ]); + expect(stateVariables["/combinedTuple"].stateValues.value.tree).eqls([ + "tuple", + "a", + "b", + "c", + "d", + "e", + "f", + ]); + }); + + it("components of math", async () => { + let core = await createTestCore({ + doenetML: ` +

+

$m

+

$m

+

Ndimensions: $m $m2.numDimensions{assignNames="numDim2"} $m3.numDimensions{assignNames="numDim3"}

+

x: $m $m2.x{assignNames="x_2"} $m3.x{assignNames="x_3"}

+

y: $m $m2.y{assignNames="y_2"} $m3.y{assignNames="y_3"}

+

z: $m $m2.z{assignNames="z_2"} $m3.z{assignNames="z_3"}

+

x1: $m $m2.x1{assignNames="x1_2"} $m3.x1{assignNames="x1_3"}

+

x2: $m $m2.x2{assignNames="x2_2"} $m3.x2{assignNames="x2_3"}

+

x3: $m $m2.x3{assignNames="x3_2"} $m3.x3{assignNames="x3_3"}

+

x4: $m $m2.x4{assignNames="x4_2"} $m3.x4{assignNames="x4_3"}

+

x:

+

y:

+

z:

+

x1:

+

x2:

+

x3:

+

x4:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let indToComp = ["x", "y", "z"]; + + async function check_values( + xs: string[], + operator: "tuple" | "vector" | "list" | "altvector", + ) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numDim1"].stateValues.value).eq(xs.length); + expect(stateVariables["/numDim2"].stateValues.value).eq(xs.length); + + for (let [ind, x] of xs.entries()) { + let comp = indToComp[ind]; + if (comp) { + expect( + stateVariables[`/${comp}`].stateValues.value.tree, + ).eq(x); + expect( + stateVariables[`/${comp}_2`].stateValues.value.tree, + ).eq(x); + expect( + stateVariables[`/${comp}_3`].stateValues.value.tree, + ).eq(x); + } + + expect( + stateVariables[`/x${ind + 1}`].stateValues.value.tree, + ).eq(x); + expect( + stateVariables[`/x${ind + 1}_2`].stateValues.value.tree, + ).eq(x); + expect( + stateVariables[`/x${ind + 1}_3`].stateValues.value.tree, + ).eq(x); + } + + let m3Operator = operator === "tuple" ? "vector" : operator; + + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + operator, + ...xs, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + operator, + ...xs, + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + m3Operator, + ...xs, + ]); + } + + await check_values(["a", "b", "c"], "tuple"); + + // change xyz 1 + await updateMathInputValue({ componentName: "/mx", latex: "d", core }); + await updateMathInputValue({ componentName: "/my", latex: "e", core }); + await updateMathInputValue({ componentName: "/mz", latex: "f", core }); + await check_values(["d", "e", "f"], "tuple"); + + // change xyz 2 + await updateMathInputValue({ + componentName: "/mx_2", + latex: "g", + core, + }); + await updateMathInputValue({ + componentName: "/my_2", + latex: "h", + core, + }); + await updateMathInputValue({ + componentName: "/mz_2", + latex: "i", + core, + }); + await check_values(["g", "h", "i"], "tuple"); + + // change xyz 3 + await updateMathInputValue({ + componentName: "/mx_3", + latex: "j", + core, + }); + await updateMathInputValue({ + componentName: "/my_3", + latex: "k", + core, + }); + await updateMathInputValue({ + componentName: "/mz_3", + latex: "l", + core, + }); + await check_values(["j", "k", "l"], "vector"); + + // change x1x2x3 1 + await updateMathInputValue({ componentName: "/mx1", latex: "m", core }); + await updateMathInputValue({ componentName: "/mx2", latex: "n", core }); + await updateMathInputValue({ componentName: "/mx3", latex: "o", core }); + await check_values(["m", "n", "o"], "vector"); + + // change x1x2x3 2 + await updateMathInputValue({ + componentName: "/mx1_2", + latex: "p", + core, + }); + await updateMathInputValue({ + componentName: "/mx2_2", + latex: "q", + core, + }); + await updateMathInputValue({ + componentName: "/mx3_2", + latex: "r", + core, + }); + await check_values(["p", "q", "r"], "vector"); + + // change x1x2x3 2 + await updateMathInputValue({ + componentName: "/mx1_3", + latex: "s", + core, + }); + await updateMathInputValue({ + componentName: "/mx2_3", + latex: "t", + core, + }); + await updateMathInputValue({ + componentName: "/mx3_3", + latex: "u", + core, + }); + await check_values(["s", "t", "u"], "vector"); + + // change to 4D list + await updateMathInputValue({ + componentName: "/m", + latex: "v,w,x,y", + core, + }); + await check_values(["v", "w", "x", "y"], "list"); + + // change x1x2x3x4 1 + await updateMathInputValue({ componentName: "/mx1", latex: "z", core }); + await updateMathInputValue({ componentName: "/mx2", latex: "a", core }); + await updateMathInputValue({ componentName: "/mx3", latex: "b", core }); + await updateMathInputValue({ componentName: "/mx4", latex: "c", core }); + await check_values(["z", "a", "b", "c"], "list"); + + // change x1x2x3x4 2 + await updateMathInputValue({ + componentName: "/mx1_2", + latex: "d", + core, + }); + await updateMathInputValue({ + componentName: "/mx2_2", + latex: "e", + core, + }); + await updateMathInputValue({ + componentName: "/mx3_2", + latex: "f", + core, + }); + await updateMathInputValue({ + componentName: "/mx4_2", + latex: "g", + core, + }); + await check_values(["d", "e", "f", "g"], "list"); + + // change to 3D alt vector + await updateMathInputValue({ + componentName: "/m", + latex: "\\langle a,b,c\\rangle", + core, + }); + await check_values(["a", "b", "c"], "altvector"); + + // change xyz 3 + await updateMathInputValue({ + componentName: "/mx_3", + latex: "j", + core, + }); + await updateMathInputValue({ + componentName: "/my_3", + latex: "k", + core, + }); + await updateMathInputValue({ + componentName: "/mz_3", + latex: "l", + core, + }); + await check_values(["j", "k", "l"], "altvector"); + }); + + it("aslist inside math, group", async () => { + let core = await createTestCore({ + doenetML: ` + + + a + b + c + + + + $grp + $grp{asList} + ($grp) + ($grp{asList}) + 2$grp + 2$grp{asList} + $grp, sin(x) + $grp{asList}, sin(x) + f($grp) + f($grp{asList}) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/nolist"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/nolist"].stateValues.text).eq("a b c"); + + expect(stateVariables["/list"].stateValues.value.tree).eqls([ + "list", + "a", + "b", + "c", + ]); + expect(stateVariables["/list"].stateValues.text).eq("a, b, c"); + + expect(stateVariables["/nolist2"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/nolist2"].stateValues.text).eq("a b c"); + + expect(stateVariables["/tuple"].stateValues.value.tree).eqls([ + "tuple", + "a", + "b", + "c", + ]); + expect(stateVariables["/tuple"].stateValues.text).eq("( a, b, c )"); + + expect(stateVariables["/doubleNoList"].stateValues.value.tree).eqls([ + "*", + 2, + "a", + "b", + "c", + ]); + expect(stateVariables["/doubleNoList"].stateValues.text).eq("2 a b c"); + + expect(stateVariables["/doubleTuple"].stateValues.value.tree).eqls([ + "*", + 2, + ["tuple", "a", "b", "c"], + ]); + expect(stateVariables["/doubleTuple"].stateValues.text).eq( + "2 ( a, b, c )", + ); + + expect(stateVariables["/appendNoList"].stateValues.value.tree).eqls([ + "list", + ["*", "a", "b", "c"], + ["apply", "sin", "x"], + ]); + expect(stateVariables["/appendNoList"].stateValues.text).eq( + "a b c, sin(x)", + ); + + expect(stateVariables["/appendToList"].stateValues.value.tree).eqls([ + "list", + "a", + "b", + "c", + ["apply", "sin", "x"], + ]); + expect(stateVariables["/appendToList"].stateValues.text).eq( + "a, b, c, sin(x)", + ); + + expect(stateVariables["/functionNoList"].stateValues.value.tree).eqls([ + "apply", + "f", + ["*", "a", "b", "c"], + ]); + expect(stateVariables["/functionNoList"].stateValues.text).eq( + "f(a b c)", + ); + + expect(stateVariables["/functionOfList"].stateValues.value.tree).eqls([ + "apply", + "f", + ["tuple", "a", "b", "c"], + ]); + expect(stateVariables["/functionOfList"].stateValues.text).eq( + "f( a, b, c )", + ); + }); + + it("aslist inside math, sequence", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $seq + $seq{asList="false"} + ($seq) + ($seq{asList="false"}) + 2$seq + 2$seq{asList="false"} + $seq, sin(x) + $seq{asList="false"}, sin(x) + sum($seq) + sum($seq{asList="false"}) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/list"].stateValues.value.tree).eqls([ + "list", + 1, + 2, + 3, + 4, + ]); + + expect(stateVariables["/nolist"].stateValues.value.tree).eq(24); + + expect(stateVariables["/tuple"].stateValues.value.tree).eqls([ + "tuple", + 1, + 2, + 3, + 4, + ]); + + expect(stateVariables["/nolist2"].stateValues.value.tree).eq(24); + + expect(stateVariables["/doubleTuple"].stateValues.value.tree).eqls([ + "tuple", + 2, + 4, + 6, + 8, + ]); + + expect(stateVariables["/doubleNoList"].stateValues.value.tree).eq(48); + + expect(stateVariables["/appendToList"].stateValues.value.tree).eqls([ + "list", + 1, + 2, + 3, + 4, + ["apply", "sin", "x"], + ]); + + expect(stateVariables["/appendNoList"].stateValues.value.tree).eqls([ + "list", + 24, + ["apply", "sin", "x"], + ]); + + expect(stateVariables["/functionOfList"].stateValues.value.tree).eq(10); + + expect(stateVariables["/functionNoList"].stateValues.value.tree).eq(24); + }); + + it("aslist inside math, map", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + $map + $map{asList="false"} + ($map) + ($map{asList="false"}) + 2$map + 2$map{asList="false"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/list"].stateValues.value.tree).eqls([ + "list", + "x", + ["*", 4, "x"], + ["*", 9, "x"], + ]); + + expect(stateVariables["/nolist"].stateValues.value.tree).eqls([ + "*", + 36, + ["^", "x", 3], + ]); + + expect(stateVariables["/tuple"].stateValues.value.tree).eqls([ + "tuple", + "x", + ["*", 4, "x"], + ["*", 9, "x"], + ]); + + expect(stateVariables["/nolist2"].stateValues.value.tree).eqls([ + "*", + 36, + ["^", "x", 3], + ]); + + expect(stateVariables["/doubleTuple"].stateValues.value.tree).eqls([ + "tuple", + ["*", 2, "x"], + ["*", 8, "x"], + ["*", 18, "x"], + ]); + + expect(stateVariables["/doubleNoList"].stateValues.value.tree).eqls([ + "*", + 72, + ["^", "x", 3], + ]); + }); + + it("math inherits unordered of children", async () => { + let core = await createTestCore({ + doenetML: ` + 2,3 + 4(2,3) + 4(2,3) + 2,3 + 4(2,3) + 2,3 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/unordered1"].stateValues.unordered).eq(true); + expect(stateVariables["/unordered2"].stateValues.unordered).eq(true); + expect(stateVariables["/unordered3"].stateValues.unordered).eq(true); + expect(stateVariables["/ordered1"].stateValues.unordered).eq(false); + expect(stateVariables["/ordered2"].stateValues.unordered).eq(false); + expect(stateVariables["/ordered3"].stateValues.unordered).eq(false); + }); + + it("copy math and overwrite unordered", async () => { + let core = await createTestCore({ + doenetML: ` + 2,3 + $ordered1{unordered name="unordered1"} + $unordered1{unordered="false" name="ordered2"} + + 2,3 + $unordered2{unordered="false" name="ordered3"} + $ordered3{unordered name="unordered3"} + + 2,3 + $unordered4{unordered="false" name="ordered4"} + $ordered4{unordered name="unordered5"} + + 2,3 + $ordered5{unordered name="unordered6"} + $unordered6{unordered="false" name="ordered6"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/unordered1"].stateValues.unordered).eq(true); + expect(stateVariables["/unordered2"].stateValues.unordered).eq(true); + expect(stateVariables["/unordered3"].stateValues.unordered).eq(true); + expect(stateVariables["/unordered4"].stateValues.unordered).eq(true); + expect(stateVariables["/unordered5"].stateValues.unordered).eq(true); + expect(stateVariables["/unordered6"].stateValues.unordered).eq(true); + expect(stateVariables["/ordered1"].stateValues.unordered).eq(false); + expect(stateVariables["/ordered2"].stateValues.unordered).eq(false); + expect(stateVariables["/ordered3"].stateValues.unordered).eq(false); + expect(stateVariables["/ordered4"].stateValues.unordered).eq(false); + expect(stateVariables["/ordered5"].stateValues.unordered).eq(false); + expect(stateVariables["/ordered6"].stateValues.unordered).eq(false); + }); + + it("copy math and overwrite unordered, change dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + +

+ 2,3 + $m1{unordered="$(../b2)" name="m2"} + $m2{unordered="$(../b3)" name="m3"} +

+ + $p1{name="p2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1/m1"].stateValues.unordered).eq(true); + expect(stateVariables["/p1/m2"].stateValues.unordered).eq(false); + expect(stateVariables["/p1/m3"].stateValues.unordered).eq(true); + expect(stateVariables["/p2/m1"].stateValues.unordered).eq(true); + expect(stateVariables["/p2/m2"].stateValues.unordered).eq(false); + expect(stateVariables["/p2/m3"].stateValues.unordered).eq(true); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/b1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1/m1"].stateValues.unordered).eq(false); + expect(stateVariables["/p1/m2"].stateValues.unordered).eq(false); + expect(stateVariables["/p1/m3"].stateValues.unordered).eq(true); + expect(stateVariables["/p2/m1"].stateValues.unordered).eq(false); + expect(stateVariables["/p2/m2"].stateValues.unordered).eq(false); + expect(stateVariables["/p2/m3"].stateValues.unordered).eq(true); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1/m1"].stateValues.unordered).eq(false); + expect(stateVariables["/p1/m2"].stateValues.unordered).eq(true); + expect(stateVariables["/p1/m3"].stateValues.unordered).eq(true); + expect(stateVariables["/p2/m1"].stateValues.unordered).eq(false); + expect(stateVariables["/p2/m2"].stateValues.unordered).eq(true); + expect(stateVariables["/p2/m3"].stateValues.unordered).eq(true); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/b3", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1/m1"].stateValues.unordered).eq(false); + expect(stateVariables["/p1/m2"].stateValues.unordered).eq(true); + expect(stateVariables["/p1/m3"].stateValues.unordered).eq(false); + expect(stateVariables["/p2/m1"].stateValues.unordered).eq(false); + expect(stateVariables["/p2/m2"].stateValues.unordered).eq(true); + expect(stateVariables["/p2/m3"].stateValues.unordered).eq(false); + }); + + it("shrink vector dimensions in inverse direction", async () => { + let core = await createTestCore({ + doenetML: ` + (x,y,z) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq( + "(x,y,z)", + ); + + await updateMathInputValue({ + latex: "(x,y)", + componentName: "/mi", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq("(x,y)"); + }); + + it("change one vector component in inverse direction does not affect other", async () => { + let core = await createTestCore({ + doenetML: ` + 1 + + + $P{name="Q" x="2$n-1"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 1, + ]); + expect(stateVariables["/Q"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 1, + ]); + + // move dependent point + await core.requestAction({ + componentName: "/Q", + actionName: "movePoint", + args: { x: -2, y: 3 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(-0.5); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 0, 3, + ]); + expect(stateVariables["/Q"].stateValues.xs.map((x) => x.tree)).eqls([ + -2, 3, + ]); + }); + + it("change one vector component in inverse direction does not affect other, original in math", async () => { + let core = await createTestCore({ + doenetML: ` + 1 + (2$n+1,1) + + + $P{name="Q" x="2$n-1"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 1, + ]); + expect(stateVariables["/Q"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 1, + ]); + + // move dependent point + await core.requestAction({ + componentName: "/Q", + actionName: "movePoint", + args: { x: -2, y: 3 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(-0.5); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 0, 3, + ]); + expect(stateVariables["/Q"].stateValues.xs.map((x) => x.tree)).eqls([ + -2, 3, + ]); + }); + + it("change one vector component in inverse direction does not affect other, through mathinput", async () => { + let core = await createTestCore({ + doenetML: ` + 1 + (2$n+1,1) + + + + $P{name="Q" x="2$n-1"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 1, + ]); + expect(stateVariables["/Q"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 1, + ]); + + // move dependent point + await core.requestAction({ + componentName: "/Q", + actionName: "movePoint", + args: { x: -2, y: 3 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(-0.5); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 0, 3, + ]); + expect(stateVariables["/Q"].stateValues.xs.map((x) => x.tree)).eqls([ + -2, 3, + ]); + + // enter value in mathinput + await updateMathInputValue({ + latex: "(6,9)", + componentName: "/coords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(2.5); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 6, 9, + ]); + expect(stateVariables["/Q"].stateValues.xs.map((x) => x.tree)).eqls([ + 4, 9, + ]); + }); + + it("copy value prop copies attributes", async () => { + let core = await createTestCore({ + doenetML: ` +

8.5203845251 + + + + +

+ +

8.5203845251 + + + + +

+ +

0.000000000000000015382487 + + + + +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq("8.52"); + expect(cleanLatex(stateVariables["/m1a"].stateValues.latex)).eq("8.52"); + expect(cleanLatex(stateVariables["/m1b"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m1c"].stateValues.latex)).eq("8.52"); + expect(cleanLatex(stateVariables["/m1d"].stateValues.latex)).eq( + "8.5204", + ); + + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m2a"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m2b"].stateValues.latex)).eq( + "8.520385", + ); + expect(cleanLatex(stateVariables["/m2c"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m2d"].stateValues.latex)).eq( + "8.520385", + ); + + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "1.54\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/m3a"].stateValues.latex)).eq( + "1.54\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/m3b"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/m3c"].stateValues.latex)).eq( + "1.54\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/m3d"].stateValues.latex)).eq("0"); + }); + + it("set vector component to undefined, copy value", async () => { + let core = await createTestCore({ + doenetML: ` + (x,y) + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq("(x,y)"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq("(x,y)"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("x"); + + await updateMathInputValue({ + latex: "", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq("(οΌΏ,y)"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "(οΌΏ,y)", + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq(""); + + await updateMathInputValue({ + latex: "q", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq("(q,y)"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq("(q,y)"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("q"); + }); + + it("set vector component to undefined, copy whole math", async () => { + let core = await createTestCore({ + doenetML: ` + (x,y) + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq("(x,y)"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq("(x,y)"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("x"); + + await updateMathInputValue({ + latex: "", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq("(οΌΏ,y)"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "(οΌΏ,y)", + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq(""); + + await updateMathInputValue({ + latex: "q", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq("(q,y)"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq("(q,y)"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("q"); + }); + + it("negative zero", async () => { + let core = await createTestCore({ + doenetML: ` +

-0

+

4 - 0

+

0 - 0

+

-0 - 0

+

0 + -0

+

0 - - 0

+

-6/-0

+ +

4 + -0

+

4 - -0

+

-0 + -0

+

-0 - -0

+

-6/-0

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq("-0"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq("4-0"); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq("0-0"); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq("-0-0"); + expect(cleanLatex(stateVariables["/m5"].stateValues.latex)).eq("0-0"); + expect(cleanLatex(stateVariables["/m6"].stateValues.latex)).eq("0--0"); + expect(cleanLatex(stateVariables["/m7"].stateValues.latex)).eq( + "-\\frac{6}{-0}", + ); + expect(cleanLatex(stateVariables["/m8"].stateValues.latex)).eq("4-0"); + expect(cleanLatex(stateVariables["/m9"].stateValues.latex)).eq("4--0"); + expect(cleanLatex(stateVariables["/m10"].stateValues.latex)).eq("-0-0"); + expect(cleanLatex(stateVariables["/m11"].stateValues.latex)).eq( + "-0--0", + ); + expect(cleanLatex(stateVariables["/m12"].stateValues.latex)).eq( + "\\frac{-6}{-0}", + ); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls(["-", 0]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + 4, + ["-", 0], + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "+", + 0, + ["-", 0], + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "+", + ["-", 0], + ["-", 0], + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "+", + 0, + ["-", 0], + ]); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "+", + 0, + ["-", ["-", 0]], + ]); + expect(stateVariables["/m7"].stateValues.value.tree).eqls([ + "-", + ["/", 6, ["-", 0]], + ]); + + expect(stateVariables["/m8"].stateValues.value.tree).eqls([ + "+", + 4, + ["-", 0], + ]); + expect(stateVariables["/m9"].stateValues.value.tree).eqls([ + "+", + 4, + ["-", ["-", 0]], + ]); + expect(stateVariables["/m10"].stateValues.value.tree).eqls([ + "+", + ["-", 0], + ["-", 0], + ]); + expect(stateVariables["/m11"].stateValues.value.tree).eqls([ + "+", + ["-", 0], + ["-", ["-", 0]], + ]); + expect(stateVariables["/m12"].stateValues.value.tree).eqls([ + "/", + -6, + ["-", 0], + ]); + }); + + it("parse <", async () => { + let core = await createTestCore({ + doenetML: ` +

x < y

+

x <= y

+

x < + y

+

x <= + y

+

x < y

+

x <= y

+ +

x < y

+

x < + y

+

x \\lt y

+

x < y

+

x \\le y

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "<", + "x", + "y", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "le", + "x", + "y", + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "<", + "x", + "y", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "le", + "x", + "y", + ]); + expect(stateVariables["/m5"].stateValues.value.tree).eqls([ + "<", + "x", + "y", + ]); + expect(stateVariables["/m6"].stateValues.value.tree).eqls([ + "le", + "x", + "y", + ]); + expect(stateVariables["/m7"].stateValues.value.tree).eqls([ + "<", + "x", + "y", + ]); + expect(stateVariables["/m8"].stateValues.value.tree).eqls([ + "<", + "x", + "y", + ]); + expect(stateVariables["/m9"].stateValues.value.tree).eqls([ + "<", + "x", + "y", + ]); + expect(stateVariables["/m10"].stateValues.value.tree).eqls([ + "<", + "x", + "y", + ]); + expect(stateVariables["/m11"].stateValues.value.tree).eqls([ + "le", + "x", + "y", + ]); + }); + + it("display rounding preserved when only one math child", async () => { + let core = await createTestCore({ + doenetML: ` +

8.5203845251 + 8.5203845251 + 8.5203845251x+526195.5352 + 8.5203845251x+526195.5352 + 8.5203845251x + 8.5203845251x + 8.5203845251 + 8.5203845251+582342.423835237238 +

+ +

+ + + + + + + +

+ +

8.5203845251 + 8.5203845251 + 8.5203845251x+526195.5352 + 8.5203845251x+526195.5352 + 8.5203845251x + 8.5203845251x + 8.5203845251 + 8.5203845251+582342.423835237238 +

+ +

+ + + + + + + +

+ +

0.000000000000000015382487 + 0.000000000000000015382487 + 0.000000000000000015382487x+526195.5352 + 0.000000000000000015382487x+526195.5352 + 0.000000000000000015382487x + 0.000000000000000015382487x + 0.000000000000000015382487 +

+ +

+ + + + + + +

+ +

8 + 8 + 8x+526195.5352 + 8x+526195.5352 + 8x + 8x + 8 +

+ +

+ + + + + + +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m1a"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m1b"].stateValues.latex)).eq( + "8.52x+526195.54", + ); + expect(cleanLatex(stateVariables["/m1c"].stateValues.latex)).eq( + "8.52x+526195.54", + ); + expect(cleanLatex(stateVariables["/m1d"].stateValues.latex)).eq( + "8.52x", + ); + expect(cleanLatex(stateVariables["/m1e"].stateValues.latex)).eq( + "8.52x", + ); + expect(cleanLatex(stateVariables["/m1f"].stateValues.latex)).eq( + "8.520385", + ); + expect(cleanLatex(stateVariables["/m1g"].stateValues.latex)).eq( + "8.5204+582342.4238", + ); + + expect(cleanLatex(stateVariables["/m1_v"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m1a_v"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m1b_v"].stateValues.latex)).eq( + "8.52x+526195.54", + ); + expect(cleanLatex(stateVariables["/m1c_v"].stateValues.latex)).eq( + "8.52x+526195.54", + ); + expect(cleanLatex(stateVariables["/m1d_v"].stateValues.latex)).eq( + "8.52x", + ); + expect(cleanLatex(stateVariables["/m1e_v"].stateValues.latex)).eq( + "8.52x", + ); + expect(cleanLatex(stateVariables["/m1f_v"].stateValues.latex)).eq( + "8.520385", + ); + expect(cleanLatex(stateVariables["/m1g_v"].stateValues.latex)).eq( + "8.5204+582342.4238", + ); + + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m2a"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m2b"].stateValues.latex)).eq( + "8.52x+526195.54", + ); + expect(cleanLatex(stateVariables["/m2c"].stateValues.latex)).eq( + "8.52x+526195.54", + ); + expect(cleanLatex(stateVariables["/m2d"].stateValues.latex)).eq( + "8.52x", + ); + expect(cleanLatex(stateVariables["/m2e"].stateValues.latex)).eq( + "8.52x", + ); + expect(cleanLatex(stateVariables["/m2f"].stateValues.latex)).eq( + "8.520385", + ); + expect(cleanLatex(stateVariables["/m2g"].stateValues.latex)).eq( + "8.5203845+582342.42", + ); + + expect(cleanLatex(stateVariables["/m2_v"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m2a_v"].stateValues.latex)).eq( + "8.5204", + ); + expect(cleanLatex(stateVariables["/m2b_v"].stateValues.latex)).eq( + "8.52x+526195.54", + ); + expect(cleanLatex(stateVariables["/m2c_v"].stateValues.latex)).eq( + "8.52x+526195.54", + ); + expect(cleanLatex(stateVariables["/m2d_v"].stateValues.latex)).eq( + "8.52x", + ); + expect(cleanLatex(stateVariables["/m2e_v"].stateValues.latex)).eq( + "8.52x", + ); + expect(cleanLatex(stateVariables["/m2f_v"].stateValues.latex)).eq( + "8.520385", + ); + expect(cleanLatex(stateVariables["/m2g_v"].stateValues.latex)).eq( + "8.5203845+582342.42", + ); + + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "1.54\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/m3a"].stateValues.latex)).eq( + "1.54\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/m3b"].stateValues.latex)).eq( + "0x+526195.54", + ); + expect(cleanLatex(stateVariables["/m3c"].stateValues.latex)).eq( + "0x+526195.54", + ); + expect(cleanLatex(stateVariables["/m3d"].stateValues.latex)).eq("0x"); + expect(cleanLatex(stateVariables["/m3e"].stateValues.latex)).eq("0x"); + expect(cleanLatex(stateVariables["/m3f"].stateValues.latex)).eq("0"); + + expect(cleanLatex(stateVariables["/m3_v"].stateValues.latex)).eq( + "1.54\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/m3a_v"].stateValues.latex)).eq( + "1.54\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/m3b_v"].stateValues.latex)).eq( + "0x+526195.54", + ); + expect(cleanLatex(stateVariables["/m3c_v"].stateValues.latex)).eq( + "0x+526195.54", + ); + expect(cleanLatex(stateVariables["/m3d_v"].stateValues.latex)).eq("0x"); + expect(cleanLatex(stateVariables["/m3e_v"].stateValues.latex)).eq("0x"); + expect(cleanLatex(stateVariables["/m3f_v"].stateValues.latex)).eq("0"); + + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq( + "8.0000", + ); + expect(cleanLatex(stateVariables["/m4a"].stateValues.latex)).eq( + "8.0000", + ); + expect(cleanLatex(stateVariables["/m4b"].stateValues.latex)).eq( + "8x+526195.54", + ); + expect(cleanLatex(stateVariables["/m4c"].stateValues.latex)).eq( + "8x+526195.54", + ); + expect(cleanLatex(stateVariables["/m4d"].stateValues.latex)).eq("8x"); + expect(cleanLatex(stateVariables["/m4e"].stateValues.latex)).eq("8x"); + expect(cleanLatex(stateVariables["/m4f"].stateValues.latex)).eq("8"); + + expect(cleanLatex(stateVariables["/m4_v"].stateValues.latex)).eq( + "8.0000", + ); + expect(cleanLatex(stateVariables["/m4a_v"].stateValues.latex)).eq( + "8.0000", + ); + expect(cleanLatex(stateVariables["/m4b_v"].stateValues.latex)).eq( + "8x+526195.54", + ); + expect(cleanLatex(stateVariables["/m4c_v"].stateValues.latex)).eq( + "8x+526195.54", + ); + expect(cleanLatex(stateVariables["/m4d_v"].stateValues.latex)).eq("8x"); + expect(cleanLatex(stateVariables["/m4e_v"].stateValues.latex)).eq("8x"); + expect(cleanLatex(stateVariables["/m4f_v"].stateValues.latex)).eq("8"); + }); + + it("negative integer to power of integer", async () => { + let core = await createTestCore({ + doenetML: ` + (-3)^2 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m"].stateValues.latex)).eq( + "(-3)^{2}", + ); + }); + + it("can get negative infinity from reciprocal when simplify", async () => { + let core = await createTestCore({ + doenetML: ` + 1/((0)(-1)) + 1/((-1)(0)) + 1/(-0) + 1/(-1(0)) + -1/0 + -1/((-1)(-0)) + + 1/((-0)(-1)) + 1/((-1)(-0)) + -1/(-0) + 1/(-1(-0)) + 1/0 + -1/((0)(-1)) + -1/((-1)(0)) + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ninf1"].stateValues.value.tree).eq(-Infinity); + expect(stateVariables["/ninf2"].stateValues.value.tree).eq(-Infinity); + expect(stateVariables["/ninf3"].stateValues.value.tree).eq(-Infinity); + expect(stateVariables["/ninf4"].stateValues.value.tree).eq(-Infinity); + expect(stateVariables["/ninf5"].stateValues.value.tree).eq(-Infinity); + expect(stateVariables["/ninf6"].stateValues.value.tree).eq(-Infinity); + + expect(stateVariables["/pinf1"].stateValues.value.tree).eq(Infinity); + expect(stateVariables["/pinf2"].stateValues.value.tree).eq(Infinity); + expect(stateVariables["/pinf3"].stateValues.value.tree).eq(Infinity); + expect(stateVariables["/pinf4"].stateValues.value.tree).eq(Infinity); + expect(stateVariables["/pinf5"].stateValues.value.tree).eq(Infinity); + expect(stateVariables["/pinf6"].stateValues.value.tree).eq(Infinity); + expect(stateVariables["/pinf7"].stateValues.value.tree).eq(Infinity); + }); + + it("display blanks", async () => { + let core = await createTestCore({ + doenetML: ` +

Display blanks:

+

x^() + /2

+

+++

+

2+

+

2+2+

+

'-_^

+

)

+

(,]

+

2+()

+

2+()+5

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "x^{}+\\frac{}{2}", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "\\operatorname{+++}", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "\\operatorname{2+}", + ); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq("2+2+"); + expect(cleanLatex(stateVariables["/m5"].stateValues.latex)).eq( + "'-_{}^{}", + ); + expect(cleanLatex(stateVariables["/m6"].stateValues.latex)).eq(""); + expect(cleanLatex(stateVariables["/m7"].stateValues.latex)).eq("(,]"); + expect(cleanLatex(stateVariables["/m8"].stateValues.latex)).eq("2+"); + expect(cleanLatex(stateVariables["/m9"].stateValues.latex)).eq("2++5"); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/displayBlanks", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "x^{\uff3f}+\\frac{\uff3f}{2}", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "\\operatorname{+++}", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "\\operatorname{2+}", + ); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq( + "2+2+\uff3f", + ); + expect(cleanLatex(stateVariables["/m5"].stateValues.latex)).eq( + "\uff3f'-\uff3f_{\uff3f}^{\uff3f}", + ); + expect(cleanLatex(stateVariables["/m6"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m7"].stateValues.latex)).eq( + "(\uff3f,\uff3f]", + ); + expect(cleanLatex(stateVariables["/m8"].stateValues.latex)).eq( + "2+\uff3f", + ); + expect(cleanLatex(stateVariables["/m9"].stateValues.latex)).eq( + "2+\uff3f+5", + ); + }); + + it("add and subtract vectors, multiply by scalar", async () => { + let core = await createTestCore({ + doenetML: ` +

Tuple2: (a,b)

+

Vector2: (c,d)

+

Alt vector2: ⟨p,q⟩

+

Interval: (e,f)

+

Tuple3: (g,h,i)

+

Vector3: (j,k,l)

+

Alt vector3: ⟨r,s,t⟩

+

$tuple2+$tuple2

+

$tuple2+$tuple2

+

$vector2+$vector2

+

$vector2+$vector2

+

$altvector2+$altvector2

+

$altvector2+$altvector2

+

$interval+$interval

+

$interval+$interval

+

$tuple2+$vector2

+

$tuple2+$vector2

+

$vector2+$tuple2

+

$vector2+$tuple2

+

$tuple2+$altvector2

+

$tuple2+$altvector2

+

$altvector2+$tuple2

+

$altvector2+$tuple2

+

$vector2+$altvector2

+

$vector2+$altvector2

+

$altvector2+$vector2

+

$altvector2+$vector2

+

$tuple2-$vector2

+

$tuple2-$vector2

+

$vector2-$tuple2

+

$vector2-$tuple2

+

$tuple2-$altvector2

+

$tuple2-$altvector2

+

$altvector2-$tuple2

+

$altvector2-$tuple2

+

$vector2-$altvector2

+

$vector2-$altvector2

+

$altvector2-$vector2

+

$altvector2-$vector2

+

$tuple2+$interval

+

$tuple2+$interval

+

$vector2+$interval

+

$vector2+$interval

+

$altvector2+$interval

+

$altvector2+$interval

+

m$tuple2

+

m$tuple2

+

m$tuple2

+

$tuple2 m

+

$tuple2 m

+

$tuple2 m

+

m$vector2

+

m$vector2

+

m$vector2

+

$vector2 m

+

$vector2 m

+

$vector2 m

+

m$altvector2

+

m$altvector2

+

m$altvector2

+

$altvector2 m

+

$altvector2 m

+

$altvector2 m

+

m$interval

+

m$interval

+

m$interval

+

$interval m

+

$interval m

+

$interval m

+

m$tuple2+$vector2*n

+

m$tuple2+$vector2*n

+

m$tuple2+$vector2*n

+

m$tuple2+$altvector2*n

+

m$tuple2+$altvector2*n

+

m$tuple2+$altvector2*n

+

m$vector2+$altvector2*n

+

m$vector2+$altvector2*n

+

m$vector2+$altvector2*n

+ +

$tuple3+$tuple3

+

$tuple3+$tuple3

+

$vector3+$vector3

+

$vector3+$vector3

+

$altvector3+$altvector3

+

$altvector3+$altvector3

+

$tuple3+$vector3

+

$tuple3+$vector3

+

$vector3+$tuple3

+

$vector3+$tuple3

+

$tuple3+$altvector3

+

$tuple3+$altvector3

+

$altvector3+$tuple3

+

$altvector3+$tuple3

+

$vector3+$altvector3

+

$vector3+$altvector3

+

$altvector3+$vector3

+

$altvector3+$vector3

+

$tuple3-$vector3

+

$tuple3-$vector3

+

$vector3-$tuple3

+

$vector3-$tuple3

+

$tuple3-$altvector3

+

$tuple3-$altvector3

+

$altvector3-$tuple3

+

$altvector3-$tuple3

+

$vector3-$altvector3

+

$vector3-$altvector3

+

$altvector3-$vector3

+

$altvector3-$vector3

+

m$tuple3

+

m$tuple3

+

m$tuple3

+

$tuple3 m

+

$tuple3 m

+

$tuple3 m

+

m$vector3

+

m$vector3

+

m$vector3

+

$vector3 m

+

$vector3 m

+

$vector3 m

+

m$altvector3

+

m$altvector3

+

m$altvector3

+

$altvector3 m

+

$altvector3 m

+

$altvector3 m

+

m$tuple3+$vector3*n

+

m$tuple3+$vector3*n

+

m$tuple3+$vector3*n

+

m$tuple3+$altvector3*n

+

m$tuple3+$altvector3*n

+

m$tuple3+$altvector3*n

+

m$vector3+$altvector3*n

+

m$vector3+$altvector3*n

+

m$vector3+$altvector3*n

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/t2t2sum"].stateValues.latex)).eq( + "(a,b)+(a,b)", + ); + expect(cleanLatex(stateVariables["/t2t2sumSimp"].stateValues.latex)).eq( + "(2a,2b)", + ); + expect(cleanLatex(stateVariables["/v2v2sum"].stateValues.latex)).eq( + "(c,d)+(c,d)", + ); + expect(cleanLatex(stateVariables["/v2v2sumSimp"].stateValues.latex)).eq( + "(2c,2d)", + ); + expect(cleanLatex(stateVariables["/a2a2sum"].stateValues.latex)).eq( + "\\langlep,q\\rangle+\\langlep,q\\rangle", + ); + expect(cleanLatex(stateVariables["/a2a2sumSimp"].stateValues.latex)).eq( + "\\langle2p,2q\\rangle", + ); + expect(cleanLatex(stateVariables["/iisum"].stateValues.latex)).eq( + "(e,f)+(e,f)", + ); + expect(cleanLatex(stateVariables["/iisumSimp"].stateValues.latex)).eq( + "2(e,f)", + ); + expect(cleanLatex(stateVariables["/t2v2sum"].stateValues.latex)).eq( + "(a,b)+(c,d)", + ); + expect(cleanLatex(stateVariables["/t2v2sumSimp"].stateValues.latex)).eq( + "(a+c,b+d)", + ); + expect(cleanLatex(stateVariables["/v2t2sum"].stateValues.latex)).eq( + "(c,d)+(a,b)", + ); + expect(cleanLatex(stateVariables["/v2t2sumSimp"].stateValues.latex)).eq( + "(a+c,b+d)", + ); + expect(cleanLatex(stateVariables["/t2a2sum"].stateValues.latex)).eq( + "(a,b)+\\langlep,q\\rangle", + ); + expect(cleanLatex(stateVariables["/t2a2sumSimp"].stateValues.latex)).eq( + "(a+p,b+q)", + ); + expect(cleanLatex(stateVariables["/a2t2sum"].stateValues.latex)).eq( + "\\langlep,q\\rangle+(a,b)", + ); + expect(cleanLatex(stateVariables["/a2t2sumSimp"].stateValues.latex)).eq( + "(a+p,b+q)", + ); + expect(cleanLatex(stateVariables["/v2a2sum"].stateValues.latex)).eq( + "(c,d)+\\langlep,q\\rangle", + ); + expect(cleanLatex(stateVariables["/v2a2sumSimp"].stateValues.latex)).eq( + "(c+p,d+q)", + ); + expect(cleanLatex(stateVariables["/a2v2sum"].stateValues.latex)).eq( + "\\langlep,q\\rangle+(c,d)", + ); + expect(cleanLatex(stateVariables["/a2v2sumSimp"].stateValues.latex)).eq( + "(c+p,d+q)", + ); + expect(cleanLatex(stateVariables["/t2v2diff"].stateValues.latex)).eq( + "(a,b)-(c,d)", + ); + expect( + cleanLatex(stateVariables["/t2v2diffSimp"].stateValues.latex), + ).eq("(a-c,b-d)"); + expect(cleanLatex(stateVariables["/v2t2diff"].stateValues.latex)).eq( + "(c,d)-(a,b)", + ); + expect( + cleanLatex(stateVariables["/v2t2diffSimp"].stateValues.latex), + ).eq("(-a+c,-b+d)"); + expect(cleanLatex(stateVariables["/t2a2diff"].stateValues.latex)).eq( + "(a,b)-\\langlep,q\\rangle", + ); + expect( + cleanLatex(stateVariables["/t2a2diffSimp"].stateValues.latex), + ).eq("(a-p,b-q)"); + expect(cleanLatex(stateVariables["/a2t2diff"].stateValues.latex)).eq( + "\\langlep,q\\rangle-(a,b)", + ); + expect( + cleanLatex(stateVariables["/a2t2diffSimp"].stateValues.latex), + ).eq("(-a+p,-b+q)"); + expect(cleanLatex(stateVariables["/v2a2diff"].stateValues.latex)).eq( + "(c,d)-\\langlep,q\\rangle", + ); + expect( + cleanLatex(stateVariables["/v2a2diffSimp"].stateValues.latex), + ).eq("(c-p,d-q)"); + expect(cleanLatex(stateVariables["/a2v2diff"].stateValues.latex)).eq( + "\\langlep,q\\rangle-(c,d)", + ); + expect( + cleanLatex(stateVariables["/a2v2diffSimp"].stateValues.latex), + ).eq("(-c+p,-d+q)"); + expect(cleanLatex(stateVariables["/t2isum"].stateValues.latex)).eq( + "(a,b)+(e,f)", + ); + expect(cleanLatex(stateVariables["/t2isumSimp"].stateValues.latex)).eq( + "(e,f)+(a,b)", + ); + expect(cleanLatex(stateVariables["/v2isum"].stateValues.latex)).eq( + "(c,d)+(e,f)", + ); + expect(cleanLatex(stateVariables["/v2isumSimp"].stateValues.latex)).eq( + "(e,f)+(c,d)", + ); + expect(cleanLatex(stateVariables["/a2isum"].stateValues.latex)).eq( + "\\langlep,q\\rangle+(e,f)", + ); + expect(cleanLatex(stateVariables["/a2isumSimp"].stateValues.latex)).eq( + "\\langlep,q\\rangle+(e,f)", + ); + expect(cleanLatex(stateVariables["/st2mul"].stateValues.latex)).eq( + "m(a,b)", + ); + expect(cleanLatex(stateVariables["/st2mulSimp"].stateValues.latex)).eq( + "(am,bm)", + ); + expect(cleanLatex(stateVariables["/st2mulExp"].stateValues.latex)).eq( + "(am,bm)", + ); + expect(cleanLatex(stateVariables["/t2smul"].stateValues.latex)).eq( + "(a,b)m", + ); + expect(cleanLatex(stateVariables["/t2smulSimp"].stateValues.latex)).eq( + "(am,bm)", + ); + expect(cleanLatex(stateVariables["/t2smulExp"].stateValues.latex)).eq( + "(am,bm)", + ); + expect(cleanLatex(stateVariables["/sv2mul"].stateValues.latex)).eq( + "m(c,d)", + ); + expect(cleanLatex(stateVariables["/sv2mulSimp"].stateValues.latex)).eq( + "(cm,dm)", + ); + expect(cleanLatex(stateVariables["/sv2mulExp"].stateValues.latex)).eq( + "(cm,dm)", + ); + expect(cleanLatex(stateVariables["/v2smul"].stateValues.latex)).eq( + "(c,d)m", + ); + expect(cleanLatex(stateVariables["/v2smulSimp"].stateValues.latex)).eq( + "(cm,dm)", + ); + expect(cleanLatex(stateVariables["/v2smulExp"].stateValues.latex)).eq( + "(cm,dm)", + ); + expect(cleanLatex(stateVariables["/sa2mul"].stateValues.latex)).eq( + "m\\langlep,q\\rangle", + ); + expect(cleanLatex(stateVariables["/sa2mulSimp"].stateValues.latex)).eq( + "\\langlemp,mq\\rangle", + ); + expect(cleanLatex(stateVariables["/sa2mulExp"].stateValues.latex)).eq( + "\\langlemp,mq\\rangle", + ); + expect(cleanLatex(stateVariables["/a2smul"].stateValues.latex)).eq( + "\\langlep,q\\ranglem", + ); + expect(cleanLatex(stateVariables["/a2smulSimp"].stateValues.latex)).eq( + "\\langlemp,mq\\rangle", + ); + expect(cleanLatex(stateVariables["/a2smulExp"].stateValues.latex)).eq( + "\\langlemp,mq\\rangle", + ); + expect(cleanLatex(stateVariables["/simul"].stateValues.latex)).eq( + "m(e,f)", + ); + expect(cleanLatex(stateVariables["/simulSimp"].stateValues.latex)).eq( + "m(e,f)", + ); + expect(cleanLatex(stateVariables["/simulExp"].stateValues.latex)).eq( + "m(e,f)", + ); + expect(cleanLatex(stateVariables["/ismul"].stateValues.latex)).eq( + "(e,f)m", + ); + expect(cleanLatex(stateVariables["/ismulSimp"].stateValues.latex)).eq( + "m(e,f)", + ); + expect(cleanLatex(stateVariables["/ismulExp"].stateValues.latex)).eq( + "m(e,f)", + ); + expect(cleanLatex(stateVariables["/st2v2ssum"].stateValues.latex)).eq( + "m(a,b)+(c,d)n", + ); + expect( + cleanLatex(stateVariables["/st2v2ssumSimp"].stateValues.latex), + ).eq("(am+cn,bm+dn)"); + expect( + cleanLatex(stateVariables["/st2v2ssumExp"].stateValues.latex), + ).eq("(am+cn,bm+dn)"); + expect(cleanLatex(stateVariables["/st2a2ssum"].stateValues.latex)).eq( + "m(a,b)+\\langlep,q\\ranglen", + ); + expect( + cleanLatex(stateVariables["/st2a2ssumSimp"].stateValues.latex), + ).eq("(am+np,bm+nq)"); + expect( + cleanLatex(stateVariables["/st2a2ssumExp"].stateValues.latex), + ).eq("(am+np,bm+nq)"); + expect(cleanLatex(stateVariables["/sv2a2ssum"].stateValues.latex)).eq( + "m(c,d)+\\langlep,q\\ranglen", + ); + expect( + cleanLatex(stateVariables["/sv2a2ssumSimp"].stateValues.latex), + ).eq("(cm+np,dm+nq)"); + expect( + cleanLatex(stateVariables["/sv2a2ssumExp"].stateValues.latex), + ).eq("(cm+np,dm+nq)"); + + expect(cleanLatex(stateVariables["/t3t3sum"].stateValues.latex)).eq( + "(g,h,i)+(g,h,i)", + ); + expect(cleanLatex(stateVariables["/t3t3sumSimp"].stateValues.latex)).eq( + "(2g,2h,2i)", + ); + expect(cleanLatex(stateVariables["/v3v3sum"].stateValues.latex)).eq( + "(j,k,l)+(j,k,l)", + ); + expect(cleanLatex(stateVariables["/v3v3sumSimp"].stateValues.latex)).eq( + "(2j,2k,2l)", + ); + expect(cleanLatex(stateVariables["/a3a3sum"].stateValues.latex)).eq( + "\\langler,s,t\\rangle+\\langler,s,t\\rangle", + ); + expect(cleanLatex(stateVariables["/a3a3sumSimp"].stateValues.latex)).eq( + "\\langle2r,2s,2t\\rangle", + ); + expect(cleanLatex(stateVariables["/t3v3sum"].stateValues.latex)).eq( + "(g,h,i)+(j,k,l)", + ); + expect(cleanLatex(stateVariables["/t3v3sumSimp"].stateValues.latex)).eq( + "(g+j,h+k,i+l)", + ); + expect(cleanLatex(stateVariables["/v3t3sum"].stateValues.latex)).eq( + "(j,k,l)+(g,h,i)", + ); + expect(cleanLatex(stateVariables["/v3t3sumSimp"].stateValues.latex)).eq( + "(g+j,h+k,i+l)", + ); + expect(cleanLatex(stateVariables["/t3a3sum"].stateValues.latex)).eq( + "(g,h,i)+\\langler,s,t\\rangle", + ); + expect(cleanLatex(stateVariables["/t3a3sumSimp"].stateValues.latex)).eq( + "(g+r,h+s,i+t)", + ); + expect(cleanLatex(stateVariables["/a3t3sum"].stateValues.latex)).eq( + "\\langler,s,t\\rangle+(g,h,i)", + ); + expect(cleanLatex(stateVariables["/a3t3sumSimp"].stateValues.latex)).eq( + "(g+r,h+s,i+t)", + ); + expect(cleanLatex(stateVariables["/v3a3sum"].stateValues.latex)).eq( + "(j,k,l)+\\langler,s,t\\rangle", + ); + expect(cleanLatex(stateVariables["/v3a3sumSimp"].stateValues.latex)).eq( + "(j+r,k+s,l+t)", + ); + expect(cleanLatex(stateVariables["/a3v3sum"].stateValues.latex)).eq( + "\\langler,s,t\\rangle+(j,k,l)", + ); + expect(cleanLatex(stateVariables["/a3v3sumSimp"].stateValues.latex)).eq( + "(j+r,k+s,l+t)", + ); + expect(cleanLatex(stateVariables["/t3v3diff"].stateValues.latex)).eq( + "(g,h,i)-(j,k,l)", + ); + expect( + cleanLatex(stateVariables["/t3v3diffSimp"].stateValues.latex), + ).eq("(g-j,h-k,i-l)"); + expect(cleanLatex(stateVariables["/v3t3diff"].stateValues.latex)).eq( + "(j,k,l)-(g,h,i)", + ); + expect( + cleanLatex(stateVariables["/v3t3diffSimp"].stateValues.latex), + ).eq("(-g+j,-h+k,-i+l)"); + expect(cleanLatex(stateVariables["/t3a3diff"].stateValues.latex)).eq( + "(g,h,i)-\\langler,s,t\\rangle", + ); + expect( + cleanLatex(stateVariables["/t3a3diffSimp"].stateValues.latex), + ).eq("(g-r,h-s,i-t)"); + expect(cleanLatex(stateVariables["/a3t3diff"].stateValues.latex)).eq( + "\\langler,s,t\\rangle-(g,h,i)", + ); + expect( + cleanLatex(stateVariables["/a3t3diffSimp"].stateValues.latex), + ).eq("(-g+r,-h+s,-i+t)"); + expect(cleanLatex(stateVariables["/v3a3diff"].stateValues.latex)).eq( + "(j,k,l)-\\langler,s,t\\rangle", + ); + expect( + cleanLatex(stateVariables["/v3a3diffSimp"].stateValues.latex), + ).eq("(j-r,k-s,l-t)"); + expect(cleanLatex(stateVariables["/a3v3diff"].stateValues.latex)).eq( + "\\langler,s,t\\rangle-(j,k,l)", + ); + expect( + cleanLatex(stateVariables["/a3v3diffSimp"].stateValues.latex), + ).eq("(-j+r,-k+s,-l+t)"); + expect(cleanLatex(stateVariables["/st3mul"].stateValues.latex)).eq( + "m(g,h,i)", + ); + expect(cleanLatex(stateVariables["/st3mulSimp"].stateValues.latex)).eq( + "(gm,hm,im)", + ); + expect(cleanLatex(stateVariables["/st3mulExp"].stateValues.latex)).eq( + "(gm,hm,im)", + ); + expect(cleanLatex(stateVariables["/t3smul"].stateValues.latex)).eq( + "(g,h,i)m", + ); + expect(cleanLatex(stateVariables["/t3smulSimp"].stateValues.latex)).eq( + "(gm,hm,im)", + ); + expect(cleanLatex(stateVariables["/t3smulExp"].stateValues.latex)).eq( + "(gm,hm,im)", + ); + expect(cleanLatex(stateVariables["/sv3mul"].stateValues.latex)).eq( + "m(j,k,l)", + ); + expect(cleanLatex(stateVariables["/sv3mulSimp"].stateValues.latex)).eq( + "(jm,km,lm)", + ); + expect(cleanLatex(stateVariables["/sv3mulExp"].stateValues.latex)).eq( + "(jm,km,lm)", + ); + expect(cleanLatex(stateVariables["/v3smul"].stateValues.latex)).eq( + "(j,k,l)m", + ); + expect(cleanLatex(stateVariables["/v3smulSimp"].stateValues.latex)).eq( + "(jm,km,lm)", + ); + expect(cleanLatex(stateVariables["/v3smulExp"].stateValues.latex)).eq( + "(jm,km,lm)", + ); + expect(cleanLatex(stateVariables["/sa3mul"].stateValues.latex)).eq( + "m\\langler,s,t\\rangle", + ); + expect(cleanLatex(stateVariables["/sa3mulSimp"].stateValues.latex)).eq( + "\\langlemr,ms,mt\\rangle", + ); + expect(cleanLatex(stateVariables["/sa3mulExp"].stateValues.latex)).eq( + "\\langlemr,ms,mt\\rangle", + ); + expect(cleanLatex(stateVariables["/a3smul"].stateValues.latex)).eq( + "\\langler,s,t\\ranglem", + ); + expect(cleanLatex(stateVariables["/a3smulSimp"].stateValues.latex)).eq( + "\\langlemr,ms,mt\\rangle", + ); + expect(cleanLatex(stateVariables["/a3smulExp"].stateValues.latex)).eq( + "\\langlemr,ms,mt\\rangle", + ); + expect(cleanLatex(stateVariables["/st3v3ssum"].stateValues.latex)).eq( + "m(g,h,i)+(j,k,l)n", + ); + expect( + cleanLatex(stateVariables["/st3v3ssumSimp"].stateValues.latex), + ).eq("(gm+jn,hm+kn,im+ln)"); + expect( + cleanLatex(stateVariables["/st3v3ssumExp"].stateValues.latex), + ).eq("(gm+jn,hm+kn,im+ln)"); + expect(cleanLatex(stateVariables["/st3a3ssum"].stateValues.latex)).eq( + "m(g,h,i)+\\langler,s,t\\ranglen", + ); + expect( + cleanLatex(stateVariables["/st3a3ssumSimp"].stateValues.latex), + ).eq("(gm+nr,hm+ns,im+nt)"); + expect( + cleanLatex(stateVariables["/st3a3ssumExp"].stateValues.latex), + ).eq("(gm+nr,hm+ns,im+nt)"); + expect(cleanLatex(stateVariables["/sv3a3ssum"].stateValues.latex)).eq( + "m(j,k,l)+\\langler,s,t\\ranglen", + ); + expect( + cleanLatex(stateVariables["/sv3a3ssumSimp"].stateValues.latex), + ).eq("(jm+nr,km+ns,lm+nt)"); + expect( + cleanLatex(stateVariables["/sv3a3ssumExp"].stateValues.latex), + ).eq("(jm+nr,km+ns,lm+nt)"); + }); + + it("add and subtract matrices, multiply by scalar", async () => { + let core = await createTestCore({ + doenetML: ` +

matrix22: \\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}

+

matrix21: \\begin{bmatrix}e\\\\f\\end{bmatrix}

+

matrix12: \\begin{bmatrix}g&h\\end{bmatrix}

+

Tuple2: (i,j)

+

Vector2: (k,l)

+

matrix22b: \\begin{bmatrix}n&o\\\\p&q\\end{bmatrix}

+

$matrix22+$matrix22

+

$matrix22+$matrix22

+

$matrix21+$matrix21

+

$matrix21+$matrix21

+

$matrix12+$matrix12

+

$matrix12+$matrix12

+

$matrix21+$tuple2

+

$matrix21+$tuple2

+

$matrix21+$vector2

+

$matrix21+$vector2

+

$matrix12+$tuple2

+

$matrix12+$tuple2

+

$matrix12+$vector2

+

$matrix12+$vector2

+

$matrix22+$matrix21

+

$matrix22+$matrix21

+

$matrix22+$matrix12

+

$matrix22+$matrix12

+

$matrix21+$matrix12

+

$matrix21+$matrix12

+

$matrix22+$matrix21+$matrix12+$matrix12+$matrix21+$matrix22

+

$matrix22+$matrix21+$matrix12+$matrix12+$matrix21+$matrix22

+ +

m$matrix22

+

m$matrix22

+

m$matrix22

+

$matrix22 m

+

$matrix22 m

+

$matrix22 m

+

m$matrix21

+

m$matrix21

+

m$matrix21

+

$matrix21 m

+

$matrix21 m

+

$matrix21 m

+

m$matrix12

+

m$matrix12

+

m$matrix12

+

$matrix12 m

+

$matrix12 m

+

$matrix12 m

+ + +

$matrix22+$matrix22b

+

$matrix22+$matrix22b

+

$matrix22-$matrix22b

+

$matrix22-$matrix22b

+

$matrix22+m$matrix22b

+

$matrix22+m$matrix22b

+

$matrix22+m$matrix22b

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m22m22sum"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}+\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/m22m22sumSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}2a&2b\\\\2c&2d\\end{bmatrix}"); + expect(cleanLatex(stateVariables["/m21m21sum"].stateValues.latex)).eq( + "\\begin{bmatrix}e\\\\f\\end{bmatrix}+\\begin{bmatrix}e\\\\f\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/m21m21sumSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}2e\\\\2f\\end{bmatrix}"); + expect(cleanLatex(stateVariables["/m12m12sum"].stateValues.latex)).eq( + "\\begin{bmatrix}g&h\\end{bmatrix}+\\begin{bmatrix}g&h\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/m12m12sumSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}2g&2h\\end{bmatrix}"); + expect(cleanLatex(stateVariables["/m21t2sum"].stateValues.latex)).eq( + "\\begin{bmatrix}e\\\\f\\end{bmatrix}+(i,j)", + ); + expect( + cleanLatex(stateVariables["/m21t2sumSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}e\\\\f\\end{bmatrix}+(i,j)"); + expect(cleanLatex(stateVariables["/m21v2sum"].stateValues.latex)).eq( + "\\begin{bmatrix}e\\\\f\\end{bmatrix}+(k,l)", + ); + expect( + cleanLatex(stateVariables["/m21v2sumSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}e\\\\f\\end{bmatrix}+(k,l)"); + expect(cleanLatex(stateVariables["/m12t2sum"].stateValues.latex)).eq( + "\\begin{bmatrix}g&h\\end{bmatrix}+(i,j)", + ); + expect( + cleanLatex(stateVariables["/m12t2sumSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}g&h\\end{bmatrix}+(i,j)"); + expect(cleanLatex(stateVariables["/m12v2sum"].stateValues.latex)).eq( + "\\begin{bmatrix}g&h\\end{bmatrix}+(k,l)", + ); + expect( + cleanLatex(stateVariables["/m12v2sumSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}g&h\\end{bmatrix}+(k,l)"); + expect(cleanLatex(stateVariables["/m22m21sum"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}+\\begin{bmatrix}e\\\\f\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/m22m21sumSimp"].stateValues.latex), + ).eq( + "\\begin{bmatrix}e\\\\f\\end{bmatrix}+\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22m12sum"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}+\\begin{bmatrix}g&h\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/m22m12sumSimp"].stateValues.latex), + ).eq( + "\\begin{bmatrix}g&h\\end{bmatrix}+\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m21m12sum"].stateValues.latex)).eq( + "\\begin{bmatrix}e\\\\f\\end{bmatrix}+\\begin{bmatrix}g&h\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/m21m12sumSimp"].stateValues.latex), + ).eq( + "\\begin{bmatrix}g&h\\end{bmatrix}+\\begin{bmatrix}e\\\\f\\end{bmatrix}", + ); + expect( + cleanLatex( + stateVariables["/m22m21m12m12m21m22sum"].stateValues.latex, + ), + ).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}+\\begin{bmatrix}e\\\\f\\end{bmatrix}+\\begin{bmatrix}g&h\\end{bmatrix}+\\begin{bmatrix}g&h\\end{bmatrix}+\\begin{bmatrix}e\\\\f\\end{bmatrix}+\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect( + cleanLatex( + stateVariables["/m22m21m12m12m21m22sumSimp"].stateValues.latex, + ), + ).eq( + "\\begin{bmatrix}2g&2h\\end{bmatrix}+\\begin{bmatrix}2e\\\\2f\\end{bmatrix}+\\begin{bmatrix}2a&2b\\\\2c&2d\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/sm22mul"].stateValues.latex)).eq( + "m\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/sm22mulSimp"].stateValues.latex)).eq( + "\\begin{bmatrix}am&bm\\\\cm&dm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/sm22mulExp"].stateValues.latex)).eq( + "\\begin{bmatrix}am&bm\\\\cm&dm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22smul"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}m", + ); + expect(cleanLatex(stateVariables["/m22smulSimp"].stateValues.latex)).eq( + "\\begin{bmatrix}am&bm\\\\cm&dm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22smulExp"].stateValues.latex)).eq( + "\\begin{bmatrix}am&bm\\\\cm&dm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/sm21mul"].stateValues.latex)).eq( + "m\\begin{bmatrix}e\\\\f\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/sm21mulSimp"].stateValues.latex)).eq( + "\\begin{bmatrix}em\\\\fm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/sm21mulExp"].stateValues.latex)).eq( + "\\begin{bmatrix}em\\\\fm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m21smul"].stateValues.latex)).eq( + "\\begin{bmatrix}e\\\\f\\end{bmatrix}m", + ); + expect(cleanLatex(stateVariables["/m21smulSimp"].stateValues.latex)).eq( + "\\begin{bmatrix}em\\\\fm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m21smulExp"].stateValues.latex)).eq( + "\\begin{bmatrix}em\\\\fm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/sm12mul"].stateValues.latex)).eq( + "m\\begin{bmatrix}g&h\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/sm12mulSimp"].stateValues.latex)).eq( + "\\begin{bmatrix}gm&hm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/sm12mulExp"].stateValues.latex)).eq( + "\\begin{bmatrix}gm&hm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m12smul"].stateValues.latex)).eq( + "\\begin{bmatrix}g&h\\end{bmatrix}m", + ); + expect(cleanLatex(stateVariables["/m12smulSimp"].stateValues.latex)).eq( + "\\begin{bmatrix}gm&hm\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m12smulExp"].stateValues.latex)).eq( + "\\begin{bmatrix}gm&hm\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m22m22b"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}+\\begin{bmatrix}n&o\\\\p&q\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22m22bSimp"].stateValues.latex)).eq( + "\\begin{bmatrix}a+n&b+o\\\\c+p&d+q\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22m22bdiff"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}-\\begin{bmatrix}n&o\\\\p&q\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/m22m22bdiffSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}a-n&b-o\\\\c-p&d-q\\end{bmatrix}"); + expect(cleanLatex(stateVariables["/m22sm22b"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}+m\\begin{bmatrix}n&o\\\\p&q\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/m22sm22bSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}a+mn&b+mo\\\\c+mp&d+mq\\end{bmatrix}"); + expect( + cleanLatex(stateVariables["/m22sm22bExpSimp"].stateValues.latex), + ).eq("\\begin{bmatrix}a+mn&b+mo\\\\c+mp&d+mq\\end{bmatrix}"); + }); + + it("matrix multiplication", async () => { + let core = await createTestCore({ + doenetML: ` +

matrix22a: \\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}

+

matrix22b: \\begin{bmatrix}e&f\\\\g&h\\end{bmatrix}

+

matrix21a: \\begin{bmatrix}i\\\\j\\end{bmatrix}

+

matrix21b: \\begin{bmatrix}k\\\\l\\end{bmatrix}

+

matrix12a: \\begin{bmatrix}m&n\\end{bmatrix}

+

matrix12b: \\begin{bmatrix}o&p\\end{bmatrix}

+

$matrix22a$matrix22b

+

$matrix22a$matrix22b

+

$matrix22b$matrix22a

+

$matrix22b$matrix22a

+

$matrix21a$matrix21b

+

$matrix21a$matrix21b

+

$matrix12a$matrix12b

+

$matrix12a$matrix12b

+

$matrix21a$matrix12a

+

$matrix21a$matrix12a

+

$matrix12a$matrix21a

+

$matrix12a$matrix21a

+

$matrix22a$matrix21a$matrix12a$matrix22b$matrix21b$matrix12b

+

$matrix22a$matrix21a$matrix12a$matrix22b$matrix21b$matrix12b

+

\\begin{pmatrix}a e i k m o + a f i l m o + a g i k n o + a h i l n o + b e j k m o + b f j l m o + b g j k n o + b h j l n o & a e i k m p + a f i l m p + a g i k n p + a h i l n p + b e j k m p + b f j l m p + b g j k n p + b h j l n p\\\\ + c e i k m o + c f i l m o + c g i k n o + c h i l n o + d e j k m o + d f j l m o + d g j k n o + d h j l n o & c e i k m p + c f i l m p + c g i k n p + c h i l n p + d e j k m p + d f j l m p + d g j k n p + d h j l n p\\end{pmatrix}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m22am22b"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}\\begin{bmatrix}e&f\\\\g&h\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22am22bExp"].stateValues.latex)).eq( + "\\begin{bmatrix}ae+bg&af+bh\\\\ce+dg&cf+dh\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22bm22a"].stateValues.latex)).eq( + "\\begin{bmatrix}e&f\\\\g&h\\end{bmatrix}\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22bm22aExp"].stateValues.latex)).eq( + "\\begin{bmatrix}ae+cf&be+df\\\\ag+ch&bg+dh\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m21am21b"].stateValues.latex)).eq( + "\\begin{bmatrix}i\\\\j\\end{bmatrix}\\begin{bmatrix}k\\\\l\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m21am21bExp"].stateValues.latex)).eq( + "\\begin{bmatrix}i\\\\j\\end{bmatrix}\\begin{bmatrix}k\\\\l\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m12am12b"].stateValues.latex)).eq( + "\\begin{bmatrix}m&n\\end{bmatrix}\\begin{bmatrix}o&p\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m12am12bExp"].stateValues.latex)).eq( + "\\begin{bmatrix}m&n\\end{bmatrix}\\begin{bmatrix}o&p\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m21am12a"].stateValues.latex)).eq( + "\\begin{bmatrix}i\\\\j\\end{bmatrix}\\begin{bmatrix}m&n\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m21am12aExp"].stateValues.latex)).eq( + "\\begin{bmatrix}im&in\\\\jm&jn\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m12am21a"].stateValues.latex)).eq( + "\\begin{bmatrix}m&n\\end{bmatrix}\\begin{bmatrix}i\\\\j\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m12am21aExp"].stateValues.latex)).eq( + "\\begin{bmatrix}im+jn\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/longmult"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}\\begin{bmatrix}i\\\\j\\end{bmatrix}\\begin{bmatrix}m&n\\end{bmatrix}\\begin{bmatrix}e&f\\\\g&h\\end{bmatrix}\\begin{bmatrix}k\\\\l\\end{bmatrix}\\begin{bmatrix}o&p\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/longmultExp"].stateValues.latex)).eq( + "\\begin{bmatrix}aeikmo+afilmo+agikno+ahilno+bejkmo+bfjlmo+bgjkno+bhjlno&aeikmp+afilmp+agiknp+ahilnp+bejkmp+bfjlmp+bgjknp+bhjlnp\\\\ceikmo+cfilmo+cgikno+chilno+dejkmo+dfjlmo+dgjkno+dhjlno&ceikmp+cfilmp+cgiknp+chilnp+dejkmp+dfjlmp+dgjknp+dhjlnp\\end{bmatrix}", + ); + expect( + cleanLatex(stateVariables["/longMultResult"].stateValues.latex), + ).eq( + "\\begin{bmatrix}aeikmo+afilmo+agikno+ahilno+bejkmo+bfjlmo+bgjkno+bhjlno&aeikmp+afilmp+agiknp+ahilnp+bejkmp+bfjlmp+bgjknp+bhjlnp\\\\ceikmo+cfilmo+cgikno+chilno+dejkmo+dfjlmo+dgjkno+dhjlno&ceikmp+cfilmp+cgiknp+chilnp+dejkmp+dfjlmp+dgjknp+dhjlnp\\end{bmatrix}", + ); + }); + + it("matrix-vector multiplication", async () => { + let core = await createTestCore({ + doenetML: ` +

matrix22: \\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}

+

tuple2: (e,f)

+

vector2: (g,h)

+

alt vector2: ⟨p,q⟩

+

$matrix22$tuple2

+

$matrix22$tuple2

+

$tuple2$matrix22

+

$tuple2$matrix22

+

$matrix22$vector2

+

$matrix22$vector2

+

$vector2$matrix22

+

$vector2$matrix22

+

$matrix22$altvector2

+

$matrix22$altvector2

+

$altvector2$matrix22

+

$altvector2$matrix22

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m22t2"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}(e,f)", + ); + expect(cleanLatex(stateVariables["/m22t2Exp"].stateValues.latex)).eq( + "(ae+bf,ce+df)", + ); + expect(cleanLatex(stateVariables["/t2m22"].stateValues.latex)).eq( + "(e,f)\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/t2m22Exp"].stateValues.latex)).eq( + "(e,f)\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22v2"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}(g,h)", + ); + expect(cleanLatex(stateVariables["/m22v2Exp"].stateValues.latex)).eq( + "(ag+bh,cg+dh)", + ); + expect(cleanLatex(stateVariables["/v2m22"].stateValues.latex)).eq( + "(g,h)\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2m22Exp"].stateValues.latex)).eq( + "(g,h)\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m22a2"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}\\langlep,q\\rangle", + ); + expect(cleanLatex(stateVariables["/m22a2Exp"].stateValues.latex)).eq( + "\\langleap+bq,cp+dq\\rangle", + ); + expect(cleanLatex(stateVariables["/a2m22"].stateValues.latex)).eq( + "\\langlep,q\\rangle\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/a2m22Exp"].stateValues.latex)).eq( + "\\langlep,q\\rangle\\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}", + ); + }); + + it("matrix and vector state variables", async () => { + let core = await createTestCore({ + doenetML: ` +

a

+

Originals: + \\begin{pmatrix} + 1 \\\\ 2 + \\end{pmatrix} + + + \\begin{pmatrix} + 1 & 2 + \\end{pmatrix} + + (1,2) + (1,2)' + (1,2)^T + 1,2 + (1,2) + (1,2)' + (1,2)^T + ⟨1,2⟩ + ⟨1,2⟩' + ⟨1,2⟩^T +

+

N dimensions: + + + + + + + + + + + + +

+

Vectors: + + + + + + + + + + + + +

+

Vectors as math: + + + + + + + + + + + + +

+

Vector x components: + + + + + + + + + + + + +

+

Vector y components: + + + + + + + + + + + + +

+

Vector x components b: + + + + + + + + + + + + +

+

Vector y components b: + + + + + + + + + + + + +

+

Matrix size: + + + + + + + + + + + + +

+

N rows: + + + + + + + + + + + + +

+

N columns: + + + + + + + + + + + + +

+

Matrices: + + + + + + + + + + + + +

+

Matrices as math: + + + + + + + + + + + + +

+

Row 1: + + + + + + + + + + + + +

+

Row 1 b: + + + + + + + + + + + + +

+

Row 1 c: + + + + + + + + + + + + +

+

Row 2: + + + + + + + + + + + + +

+

Row 2 b: + + + + + + + + + + + + +

+

Row 2 c: + + + + + + + + + + + + +

+

Column 1: + + + + + + + + + + + + +

+

Column 1 b: + + + + + + + + + + + + +

+

Column 2: + + + + + + + + + + + + +

+

Column 2 b: + + + + + + + + + + + + +

+ +

Matrix entry 12: + + + + + + + + + + + + +

+

Matrix entry 12 b: + + + + + + + + + + + + +

+

Matrix entry 12 c: + + + + + + + + + + + + +

+

Matrix entry 12 d: + + + + + + + + + + + + +

+

Matrix entry 12 e: + + + + + + + + + + + + +

+

Matrix entry 12 f: + + + + + + + + + + + + +

+

Matrix entry 21: + + + + + + + + + + + + +

+

Matrix entry 21 b: + + + + + + + + + + + + +

+

Matrix entry 21 c: + + + + + + + + + + + + +

+

Matrix entry 21 d: + + + + + + + + + + + + +

+

Matrix entry 21 e: + + + + + + + + + + + + +

+

Matrix entry 21 f: + + + + + + + + + + + + +

+ +

Graph vectors

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

Change matrices

+

+

+

+

+

+

+

+

+

+

+

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/v1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3"].stateValues.latex)).eq("(1,2)"); + expect(cleanLatex(stateVariables["/v4"].stateValues.latex)).eq( + "(1,2)'", + ); + expect(cleanLatex(stateVariables["/v5"].stateValues.latex)).eq( + "(1,2)^{T}", + ); + expect(cleanLatex(stateVariables["/v6"].stateValues.latex)).eq("1,2"); + expect(cleanLatex(stateVariables["/v7"].stateValues.latex)).eq("(1,2)"); + expect(cleanLatex(stateVariables["/v8"].stateValues.latex)).eq( + "(1,2)'", + ); + expect(cleanLatex(stateVariables["/v9"].stateValues.latex)).eq( + "(1,2)^{T}", + ); + expect(cleanLatex(stateVariables["/v10"].stateValues.latex)).eq( + "\\langle1,2\\rangle", + ); + expect(cleanLatex(stateVariables["/v11"].stateValues.latex)).eq( + "\\langle1,2\\rangle'", + ); + expect(cleanLatex(stateVariables["/v12"].stateValues.latex)).eq( + "\\langle1,2\\rangle^{T}", + ); + + expect(stateVariables["/v1nd"].stateValues.value).eq(2); + expect(stateVariables["/v2nd"].stateValues.value).eq(2); + expect(stateVariables["/v3nd"].stateValues.value).eq(2); + expect(stateVariables["/v4nd"].stateValues.value).eq(2); + expect(stateVariables["/v5nd"].stateValues.value).eq(2); + expect(stateVariables["/v6nd"].stateValues.value).eq(2); + expect(stateVariables["/v7nd"].stateValues.value).eq(2); + expect(stateVariables["/v8nd"].stateValues.value).eq(2); + expect(stateVariables["/v9nd"].stateValues.value).eq(2); + expect(stateVariables["/v10nd"].stateValues.value).eq(2); + expect(stateVariables["/v11nd"].stateValues.value).eq(2); + expect(stateVariables["/v12nd"].stateValues.value).eq(2); + + expect(cleanLatex(stateVariables["/v1v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v2v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v3v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v4v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v5v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v6v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v7v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v8v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v9v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v10v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v11v"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v12v"].stateValues.latex)).eq( + "(1,2)", + ); + + expect(cleanLatex(stateVariables["/v1vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v2vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v3vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v4vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v5vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v6vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v7vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v8vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v9vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v10vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v11vm"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/v12vm"].stateValues.latex)).eq( + "(1,2)", + ); + + expect(cleanLatex(stateVariables["/v1x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v2x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v3x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v4x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v5x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v6x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v7x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v8x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v9x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v10x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v11x"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v12x"].stateValues.latex)).eq("1"); + + expect(cleanLatex(stateVariables["/v1xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v2xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v3xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v4xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v5xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v6xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v7xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v8xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v9xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v10xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v11xb"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/v12xb"].stateValues.latex)).eq("1"); + + expect(cleanLatex(stateVariables["/v1y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v2y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v3y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v4y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v5y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v6y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v7y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v8y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v9y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v10y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v11y"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v12y"].stateValues.latex)).eq("2"); + + expect(cleanLatex(stateVariables["/v1yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v2yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v3yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v4yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v5yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v6yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v7yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v8yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v9yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v10yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v11yb"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v12yb"].stateValues.latex)).eq("2"); + + expect(stateVariables["/v1ms"].stateValues.numbers).eqls([2, 1]); + expect(stateVariables["/v2ms"].stateValues.numbers).eqls([1, 2]); + expect(stateVariables["/v3ms"].stateValues.numbers).eqls([2, 1]); + expect(stateVariables["/v4ms"].stateValues.numbers).eqls([1, 2]); + expect(stateVariables["/v5ms"].stateValues.numbers).eqls([1, 2]); + expect(stateVariables["/v6ms"].stateValues.numbers).eqls([2, 1]); + expect(stateVariables["/v7ms"].stateValues.numbers).eqls([2, 1]); + expect(stateVariables["/v8ms"].stateValues.numbers).eqls([1, 2]); + expect(stateVariables["/v9ms"].stateValues.numbers).eqls([1, 2]); + expect(stateVariables["/v10ms"].stateValues.numbers).eqls([2, 1]); + expect(stateVariables["/v11ms"].stateValues.numbers).eqls([1, 2]); + expect(stateVariables["/v12ms"].stateValues.numbers).eqls([1, 2]); + + expect(stateVariables["/v1nr"].stateValues.value).eq(2); + expect(stateVariables["/v2nr"].stateValues.value).eq(1); + expect(stateVariables["/v3nr"].stateValues.value).eq(2); + expect(stateVariables["/v4nr"].stateValues.value).eq(1); + expect(stateVariables["/v5nr"].stateValues.value).eq(1); + expect(stateVariables["/v6nr"].stateValues.value).eq(2); + expect(stateVariables["/v7nr"].stateValues.value).eq(2); + expect(stateVariables["/v8nr"].stateValues.value).eq(1); + expect(stateVariables["/v9nr"].stateValues.value).eq(1); + expect(stateVariables["/v10nr"].stateValues.value).eq(2); + expect(stateVariables["/v11nr"].stateValues.value).eq(1); + expect(stateVariables["/v12nr"].stateValues.value).eq(1); + + expect(stateVariables["/v1nc"].stateValues.value).eq(1); + expect(stateVariables["/v2nc"].stateValues.value).eq(2); + expect(stateVariables["/v3nc"].stateValues.value).eq(1); + expect(stateVariables["/v4nc"].stateValues.value).eq(2); + expect(stateVariables["/v5nc"].stateValues.value).eq(2); + expect(stateVariables["/v6nc"].stateValues.value).eq(1); + expect(stateVariables["/v7nc"].stateValues.value).eq(1); + expect(stateVariables["/v8nc"].stateValues.value).eq(2); + expect(stateVariables["/v9nc"].stateValues.value).eq(2); + expect(stateVariables["/v10nc"].stateValues.value).eq(1); + expect(stateVariables["/v11nc"].stateValues.value).eq(2); + expect(stateVariables["/v12nc"].stateValues.value).eq(2); + + expect(cleanLatex(stateVariables["/v1m"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3m"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6m"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7m"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10m"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1r2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2r2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3r2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4r2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5r2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6r2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7r2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8r2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9r2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10r2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11r2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12r2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1c2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3c2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6c2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7c2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10c2"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v4c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v5c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v6c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v7c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v8c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v9c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v10c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v11c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v12c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/v1me12"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v2me12"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v3me12"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v4me12"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v5me12"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v6me12"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v7me12"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v8me12"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v9me12"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v10me12"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v11me12"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v12me12"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/v1me12b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v2me12b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v3me12b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v4me12b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v5me12b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v6me12b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v7me12b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v8me12b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v9me12b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v10me12b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v11me12b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v12me12b"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/v1me12c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v2me12c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v3me12c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v4me12c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v5me12c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v6me12c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v7me12c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v8me12c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v9me12c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v10me12c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v11me12c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v12me12c"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/v1me12d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v2me12d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v3me12d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v4me12d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v5me12d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v6me12d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v7me12d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v8me12d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v9me12d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v10me12d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v11me12d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v12me12d"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/v1me12e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v2me12e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v3me12e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v4me12e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v5me12e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v6me12e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v7me12e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v8me12e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v9me12e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v10me12e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v11me12e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v12me12e"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/v1me12f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v2me12f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v3me12f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v4me12f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v5me12f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v6me12f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v7me12f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v8me12f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v9me12f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v10me12f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v11me12f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v12me12f"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/v1me21"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v2me21"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v3me21"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v4me21"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v5me21"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v6me21"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v7me21"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/v8me21"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v9me21"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v10me21"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v11me21"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v12me21"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/v1me21b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v2me21b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v3me21b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v4me21b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v5me21b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v6me21b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v7me21b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v8me21b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v9me21b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v10me21b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v11me21b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v12me21b"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/v1me21c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v2me21c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v3me21c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v4me21c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v5me21c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v6me21c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v7me21c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v8me21c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v9me21c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v10me21c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v11me21c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v12me21c"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/v1me21d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v2me21d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v3me21d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v4me21d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v5me21d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v6me21d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v7me21d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v8me21d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v9me21d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v10me21d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v11me21d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v12me21d"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/v1me21e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v2me21e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v3me21e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v4me21e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v5me21e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v6me21e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v7me21e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v8me21e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v9me21e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v10me21e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v11me21e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v12me21e"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/v1me21f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v2me21f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v3me21f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v4me21f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v5me21f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v6me21f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v7me21f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v8me21f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v9me21f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v10me21f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/v11me21f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/v12me21f"].stateValues.latex)).eq( + "\uff3f", + ); + + // move vectors + + await core.requestAction({ + actionName: "moveVector", + componentName: "/v1vb", + args: { + headcoords: [2, 1], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v2vb", + args: { + headcoords: [2, 2], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v3vb", + args: { + headcoords: [2, 3], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v4vb", + args: { + headcoords: [2, 4], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v5vb", + args: { + headcoords: [2, 5], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v6vb", + args: { + headcoords: [2, 6], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v7vb", + args: { + headcoords: [2, 7], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v8vb", + args: { + headcoords: [2, 8], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v9vb", + args: { + headcoords: [2, 9], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v10vb", + args: { + headcoords: [2, 10], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v11vb", + args: { + headcoords: [2, 11], + }, + event: null, + }); + await core.requestAction({ + actionName: "moveVector", + componentName: "/v12vb", + args: { + headcoords: [2, 12], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/v1"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\\\1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2"].stateValues.latex)).eq( + "\\begin{bmatrix}2&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3"].stateValues.latex)).eq("(2,3)"); + expect(cleanLatex(stateVariables["/v4"].stateValues.latex)).eq( + "(2,4)'", + ); + expect(cleanLatex(stateVariables["/v5"].stateValues.latex)).eq( + "(2,5)^{T}", + ); + expect(cleanLatex(stateVariables["/v6"].stateValues.latex)).eq("2,6"); + expect(cleanLatex(stateVariables["/v7"].stateValues.latex)).eq("(2,7)"); + expect(cleanLatex(stateVariables["/v8"].stateValues.latex)).eq( + "(2,8)'", + ); + expect(cleanLatex(stateVariables["/v9"].stateValues.latex)).eq( + "(2,9)^{T}", + ); + expect(cleanLatex(stateVariables["/v10"].stateValues.latex)).eq( + "\\langle2,10\\rangle", + ); + expect(cleanLatex(stateVariables["/v11"].stateValues.latex)).eq( + "\\langle2,11\\rangle'", + ); + expect(cleanLatex(stateVariables["/v12"].stateValues.latex)).eq( + "\\langle2,12\\rangle^{T}", + ); + + // change from matrix inputs + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi1", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-1", + componentName: "/mi1", + rowInd: 1, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi2", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-2", + componentName: "/mi2", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi3", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-3", + componentName: "/mi3", + rowInd: 1, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi4", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-4", + componentName: "/mi4", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi5", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-5", + componentName: "/mi5", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi6", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-6", + componentName: "/mi6", + rowInd: 1, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi7", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-7", + componentName: "/mi7", + rowInd: 1, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi8", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-8", + componentName: "/mi8", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi9", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-9", + componentName: "/mi9", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi10", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-10", + componentName: "/mi10", + rowInd: 1, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi11", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-11", + componentName: "/mi11", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "3", + componentName: "/mi12", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "-12", + componentName: "/mi12", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/v1"].stateValues.latex)).eq( + "\\begin{bmatrix}3\\\\-1\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v2"].stateValues.latex)).eq( + "\\begin{bmatrix}3&-2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/v3"].stateValues.latex)).eq( + "(3,-3)", + ); + expect(cleanLatex(stateVariables["/v4"].stateValues.latex)).eq( + "(3,-4)'", + ); + expect(cleanLatex(stateVariables["/v5"].stateValues.latex)).eq( + "(3,-5)^{T}", + ); + expect(cleanLatex(stateVariables["/v6"].stateValues.latex)).eq("3,-6"); + expect(cleanLatex(stateVariables["/v7"].stateValues.latex)).eq( + "(3,-7)", + ); + expect(cleanLatex(stateVariables["/v8"].stateValues.latex)).eq( + "(3,-8)'", + ); + expect(cleanLatex(stateVariables["/v9"].stateValues.latex)).eq( + "(3,-9)^{T}", + ); + expect(cleanLatex(stateVariables["/v10"].stateValues.latex)).eq( + "\\langle3,-10\\rangle", + ); + expect(cleanLatex(stateVariables["/v11"].stateValues.latex)).eq( + "\\langle3,-11\\rangle'", + ); + expect(cleanLatex(stateVariables["/v12"].stateValues.latex)).eq( + "\\langle3,-12\\rangle^{T}", + ); + }); + + it("matrix state variables, non vector matrices", async () => { + let core = await createTestCore({ + doenetML: ` +

Originals: + \\begin{pmatrix} + 1 & 2\\\\ + 3 & 4\\\\ + 5 & 6 + \\end{pmatrix} + + + 1 2 + 3 4 + 5 6 + + + 1 3 5 + 2 4 6 + +

+

Matrix size: + + + +

+

N rows: + + + +

+

N columns: + + + +

+

Matrices: + + + +

+

Matrices as math: + + + +

+

Row 1: + + + +

+

Row 1 b: + + + +

+

Row 1 c: + + + +

+

Row 2: + + + +

+

Row 2 b: + + + +

+

Row 2 c: + + + +

+

Row 3: + + + +

+

Row 3 b: + + + +

+

Row 3 c: + + + +

+

Row 4: + + + +

+

Row 4 b: + + + +

+

Row 4 c: + + + +

+

Column 1: + + + +

+

Column 1 b: + + + +

+

Column 2: + + + +

+

Column 2 b: + + + +

+

Column 3: + + + +

+

Column 3 b: + + + +

+ +

Matrix entry 12: + + + +

+

Matrix entry 12 b: + + + +

+

Matrix entry 12 c: + + + +

+

Matrix entry 12 d: + + + +

+

Matrix entry 12 e: + + + +

+

Matrix entry 12 f: + + + +

+

Matrix entry 31: + + + +

+

Matrix entry 31 b: + + + +

+

Matrix entry 31 c: + + + +

+

Matrix entry 31 d: + + + +

+

Matrix entry 31 e: + + + +

+

Matrix entry 31 f: + + + +

+

Matrix entry 23: + + + +

+

Matrix entry 23 b: + + + +

+

Matrix entry 23 c: + + + +

+

Matrix entry 23 d: + + + +

+

Matrix entry 23 e: + + + +

+

Matrix entry 23 f: + + + +

+ + +

Change matrices

+

+

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + + expect(stateVariables["/m1ms"].stateValues.numbers).eqls([3, 2]); + expect(stateVariables["/m2ms"].stateValues.numbers).eqls([3, 2]); + expect(stateVariables["/m3ms"].stateValues.numbers).eqls([3, 2]); + + expect(stateVariables["/m1nr"].stateValues.value).eq(3); + expect(stateVariables["/m2nr"].stateValues.value).eq(3); + expect(stateVariables["/m3nr"].stateValues.value).eq(3); + + expect(stateVariables["/m1nc"].stateValues.value).eq(2); + expect(stateVariables["/m2nc"].stateValues.value).eq(2); + expect(stateVariables["/m3nc"].stateValues.value).eq(2); + + expect(cleanLatex(stateVariables["/m1m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3m"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3mm"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\\\3&4\\\\5&6\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r1"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r1c"].stateValues.latex)).eq( + "\\begin{bmatrix}1&2\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r2"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r2"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r2"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r2b"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r2c"].stateValues.latex)).eq( + "\\begin{bmatrix}3&4\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r3"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r3"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r3"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r3b"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r3b"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r3b"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r3c"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r3c"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r3c"].stateValues.latex)).eq( + "\\begin{bmatrix}5&6\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r4"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r4"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r4"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r4b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r4b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r4b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1r4c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2r4c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3r4c"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\3\\\\5\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\3\\\\5\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3c1"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\3\\\\5\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\3\\\\5\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\3\\\\5\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3c1b"].stateValues.latex)).eq( + "\\begin{bmatrix}1\\\\3\\\\5\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\\\4\\\\6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\\\4\\\\6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3c2"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\\\4\\\\6\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\\\4\\\\6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\\\4\\\\6\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3c2b"].stateValues.latex)).eq( + "\\begin{bmatrix}2\\\\4\\\\6\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1c3"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2c3"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3c3"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1c3b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2c3b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3c3b"].stateValues.latex)).eq( + "\\begin{bmatrix}\\end{bmatrix}", + ); + + expect(cleanLatex(stateVariables["/m1me12"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/m2me12"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/m3me12"].stateValues.latex)).eq("2"); + + expect(cleanLatex(stateVariables["/m1me12b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m2me12b"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m3me12b"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/m1me12c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m2me12c"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m3me12c"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/m1me12d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m2me12d"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m3me12d"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/m1me12e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m2me12e"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m3me12e"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/m1me12f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m2me12f"].stateValues.latex)).eq( + "2", + ); + expect(cleanLatex(stateVariables["/m3me12f"].stateValues.latex)).eq( + "2", + ); + + expect(cleanLatex(stateVariables["/m1me31"].stateValues.latex)).eq("5"); + expect(cleanLatex(stateVariables["/m2me31"].stateValues.latex)).eq("5"); + expect(cleanLatex(stateVariables["/m3me31"].stateValues.latex)).eq("5"); + + expect(cleanLatex(stateVariables["/m1me31b"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m2me31b"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m3me31b"].stateValues.latex)).eq( + "5", + ); + + expect(cleanLatex(stateVariables["/m1me31c"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m2me31c"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m3me31c"].stateValues.latex)).eq( + "5", + ); + + expect(cleanLatex(stateVariables["/m1me31d"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m2me31d"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m3me31d"].stateValues.latex)).eq( + "5", + ); + + expect(cleanLatex(stateVariables["/m1me31e"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m2me31e"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m3me31e"].stateValues.latex)).eq( + "5", + ); + + expect(cleanLatex(stateVariables["/m1me31f"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m2me31f"].stateValues.latex)).eq( + "5", + ); + expect(cleanLatex(stateVariables["/m3me31f"].stateValues.latex)).eq( + "5", + ); + + expect(cleanLatex(stateVariables["/m1me23"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m2me23"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m3me23"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/m1me23b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m2me23b"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m3me23b"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/m1me23c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m2me23c"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m3me23c"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/m1me23d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m2me23d"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m3me23d"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/m1me23e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m2me23e"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m3me23e"].stateValues.latex)).eq( + "\uff3f", + ); + + expect(cleanLatex(stateVariables["/m1me23f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m2me23f"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/m3me23f"].stateValues.latex)).eq( + "\uff3f", + ); + + // change from matrix inputs + await updateMatrixInputValue({ + latex: "a", + componentName: "/mi1", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "b", + componentName: "/mi1", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "c", + componentName: "/mi1", + rowInd: 1, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "d", + componentName: "/mi1", + rowInd: 1, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "e", + componentName: "/mi1", + rowInd: 2, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "f", + componentName: "/mi1", + rowInd: 2, + colInd: 1, + core, + stateVariables, + }); + + await updateMatrixInputValue({ + latex: "g", + componentName: "/mi2", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "h", + componentName: "/mi2", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "i", + componentName: "/mi2", + rowInd: 1, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "j", + componentName: "/mi2", + rowInd: 1, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "k", + componentName: "/mi2", + rowInd: 2, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "l", + componentName: "/mi2", + rowInd: 2, + colInd: 1, + core, + stateVariables, + }); + + await updateMatrixInputValue({ + latex: "m", + componentName: "/mi3", + rowInd: 0, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "n", + componentName: "/mi3", + rowInd: 0, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "o", + componentName: "/mi3", + rowInd: 1, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "p", + componentName: "/mi3", + rowInd: 1, + colInd: 1, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "q", + componentName: "/mi3", + rowInd: 2, + colInd: 0, + core, + stateVariables, + }); + await updateMatrixInputValue({ + latex: "r", + componentName: "/mi3", + rowInd: 2, + colInd: 1, + core, + stateVariables, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "\\begin{bmatrix}a&b\\\\c&d\\\\e&f\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "\\begin{bmatrix}g&h\\\\i&j\\\\k&l\\end{bmatrix}", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "\\begin{bmatrix}m&n\\\\o&p\\\\q&r\\end{bmatrix}", + ); + }); + + it("simplify complex numbers", async () => { + let core = await createTestCore({ + doenetML: ` + i^2 + i^3 + i^4 + (1+i)(1-i) + aibici + (a+bi)(c+di) + (a+bi)(a-bi) + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/e1"].stateValues.latex)).eq("-1"); + expect(cleanLatex(stateVariables["/e2"].stateValues.latex)).eq("-i"); + expect(cleanLatex(stateVariables["/e3"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/e4"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/e5"].stateValues.latex)).eq("-abci"); + expect(cleanLatex(stateVariables["/e6"].stateValues.latex)).eq( + "ac+adi+bci-bd", + ); + expect(cleanLatex(stateVariables["/e7"].stateValues.latex)).eq( + "a^{2}+b^{2}", + ); + }); + + it("parse scientific notation", async () => { + let core = await createTestCore({ + doenetML: ` +

2E+3+3E+2 + 2E+3+3E+2 + 2E+3+3E+2 + 2E+3+3E+2

+ + +

2E+3+3E+2 + 2E+3+3E+2 + 2E+3+3E+2 + 2E+3+3E+2

+ +

2E3+3E2 + 2E3+3E2 + 2E3+3E2 + 2E3+3E2 +

+ +

2E3+3E2 + 2E3+3E2 + 2E3+3E2 + 2E3+3E2 +

+ +

+ +

+

2E+3+3E+2

+

2E+3+3E+2

+

2E3+3E2

+

2E3+3E2

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq("5E+5"); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq("2300"); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "3E+2002", + ); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq( + "2E+303", + ); + expect(cleanLatex(stateVariables["/m1a"].stateValues.latex)).eq("5E+5"); + expect(cleanLatex(stateVariables["/m2a"].stateValues.latex)).eq("2300"); + expect(cleanLatex(stateVariables["/m3a"].stateValues.latex)).eq( + "3E+2002", + ); + expect(cleanLatex(stateVariables["/m4a"].stateValues.latex)).eq( + "2E+303", + ); + + expect(cleanLatex(stateVariables["/m5"].stateValues.latex)).eq( + "3\\operatorname{E2}+2\\operatorname{E3}", + ); + expect(cleanLatex(stateVariables["/m6"].stateValues.latex)).eq("2300"); + expect(cleanLatex(stateVariables["/m7"].stateValues.latex)).eq( + "3\\operatorname{E2}+2000", + ); + expect(cleanLatex(stateVariables["/m8"].stateValues.latex)).eq( + "2\\operatorname{E3}+300", + ); + expect(cleanLatex(stateVariables["/m5a"].stateValues.latex)).eq( + "3\\operatorname{E2}+2\\operatorname{E3}", + ); + expect(cleanLatex(stateVariables["/m6a"].stateValues.latex)).eq("2300"); + expect(cleanLatex(stateVariables["/m7a"].stateValues.latex)).eq( + "3\\operatorname{E2}+2000", + ); + expect(cleanLatex(stateVariables["/m8a"].stateValues.latex)).eq( + "2\\operatorname{E3}+300", + ); + + expect(cleanLatex(stateVariables["/m9"].stateValues.latex)).eq("5E+5"); + expect(cleanLatex(stateVariables["/m9a"].stateValues.latex)).eq("5E+5"); + expect(cleanLatex(stateVariables["/m10"].stateValues.latex)).eq( + "3\\operatorname{E2}+2\\operatorname{E3}", + ); + expect(cleanLatex(stateVariables["/m10a"].stateValues.latex)).eq( + "3\\operatorname{E2}+2\\operatorname{E3}", + ); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/p1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m9"].stateValues.latex)).eq( + "2E+303", + ); + expect(cleanLatex(stateVariables["/m9a"].stateValues.latex)).eq( + "2E+303", + ); + expect(cleanLatex(stateVariables["/m10"].stateValues.latex)).eq( + "2\\operatorname{E3}+300", + ); + expect(cleanLatex(stateVariables["/m10a"].stateValues.latex)).eq( + "2\\operatorname{E3}+300", + ); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/p2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m9"].stateValues.latex)).eq("2300"); + expect(cleanLatex(stateVariables["/m9a"].stateValues.latex)).eq("2300"); + expect(cleanLatex(stateVariables["/m10"].stateValues.latex)).eq("2300"); + expect(cleanLatex(stateVariables["/m10a"].stateValues.latex)).eq( + "2300", + ); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/p1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m9"].stateValues.latex)).eq( + "3E+2002", + ); + expect(cleanLatex(stateVariables["/m9a"].stateValues.latex)).eq( + "3E+2002", + ); + expect(cleanLatex(stateVariables["/m10"].stateValues.latex)).eq( + "3\\operatorname{E2}+2000", + ); + expect(cleanLatex(stateVariables["/m10a"].stateValues.latex)).eq( + "3\\operatorname{E2}+2000", + ); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/p2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m9"].stateValues.latex)).eq("5E+5"); + expect(cleanLatex(stateVariables["/m9a"].stateValues.latex)).eq("5E+5"); + expect(cleanLatex(stateVariables["/m10"].stateValues.latex)).eq( + "3\\operatorname{E2}+2\\operatorname{E3}", + ); + expect(cleanLatex(stateVariables["/m10a"].stateValues.latex)).eq( + "3\\operatorname{E2}+2\\operatorname{E3}", + ); + }); + + it("subscripts and superscripts numbers to unicode text", async () => { + let core = await createTestCore({ + doenetML: ` +

2x_1y_23+z_456-a_(7+8-90)

+

2x^1y^23+z^456-a^(7+8-90)

+

a^2 - b_2

+

$m1.text

+

$m2.text

+

$m3.text

+

aβ‚‚-bΒ²

+ +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1t"].stateValues.text).eq( + "2 x₁ y₂₃ + z₄₅₆ - aβ‚‡β‚Šβ‚ˆβ‚‹β‚‰β‚€", + ); + expect(stateVariables["/m2t"].stateValues.text).eq( + "2 xΒΉ yΒ²Β³ + z⁴⁡⁢ - a⁷⁺⁸⁻⁹⁰", + ); + expect(stateVariables["/m3t"].stateValues.text).eq("aΒ² - bβ‚‚"); + + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m3t"].stateValues.text).eq("aβ‚‚ - bΒ²"); + }); + + it("math in graph", async () => { + let core = await createTestCore({ + doenetML: ` + + $content1 + e^(-x^2) + + +

Anchor 1 coordinates:

+

Anchor 2 coordinates:

+

Change anchor 1 coordinates:

+

Change anchor 2 coordinates:

+

Position from anchor 1: $math1.positionFromAnchor

+

Position from anchor 2: $math2.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

+

Content 1

+

Content 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["/math1anchor"].stateValues.latex)).eq( + "(1,3)", + ); + expect(cleanLatex(stateVariables["/math2anchor"].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(cleanLatex(stateVariables["/math1"].stateValues.latex)).eq( + "\\frac{x^{2}}{3}", + ); + expect(cleanLatex(stateVariables["/math2"].stateValues.latex)).eq( + "e^{-x^{2}}", + ); + + // move maths by dragging + await core.requestAction({ + actionName: "moveMath", + componentName: "/math1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveMath", + componentName: "/math2", + args: { x: 4, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "(-2,3)", + ); + expect(cleanLatex(stateVariables["/math2anchor"].stateValues.latex)).eq( + "(4,-5)", + ); + + // move maths 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["/math1anchor"].stateValues.latex)).eq( + "(6,7)", + ); + expect(cleanLatex(stateVariables["/math2anchor"].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 maths by dragging + await core.requestAction({ + actionName: "moveMath", + componentName: "/math1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveMath", + componentName: "/math2", + args: { x: -8, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "(6,7)", + ); + expect(cleanLatex(stateVariables["/math2anchor"].stateValues.latex)).eq( + "(8,9)", + ); + + // change content of math + await updateMathInputValue({ + latex: "\\frac{x^{2}}{3}+5", + componentName: "/content1", + core, + }); + await updateMathInputValue({ + latex: "e^{-x^{2}}-a", + componentName: "/content2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1"].stateValues.latex)).eq( + "\\frac{x^{2}}{3}+5", + ); + expect(cleanLatex(stateVariables["/math2"].stateValues.latex)).eq( + "e^{-x^{2}}-a", + ); + + // 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: "moveMath", + componentName: "/math1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveMath", + componentName: "/math2", + args: { x: -8, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "(-10,-9)", + ); + expect(cleanLatex(stateVariables["/math2anchor"].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 math 1 + await updateMathInputValue({ + latex: "(3,4)", + componentName: "/anchorCoords2", + core, + }); + await updateMathInputValue({ + latex: "(1,2)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/math2anchor"].stateValues.latex)).eq( + "(-8,-7)", + ); + + // cannot move maths by dragging + await core.requestAction({ + actionName: "moveMath", + componentName: "/math1", + args: { x: 4, y: 6 }, + event: null, + }); + await core.requestAction({ + actionName: "moveMath", + componentName: "/math2", + args: { x: 7, y: 8 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/math2anchor"].stateValues.latex)).eq( + "(-8,-7)", + ); + + // can change position from anchor only for math 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", + ); + + // 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 math 1 + await updateMathInputValue({ + latex: "(7,8)", + componentName: "/anchorCoords2", + core, + }); + await updateMathInputValue({ + latex: "(5,6)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "(5,6)", + ); + expect(cleanLatex(stateVariables["/math2anchor"].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 content only for math 1 + await updateMathInputValue({ + latex: "e^{-x^{2}}-a+y", + componentName: "/content2", + core, + }); + await updateMathInputValue({ + latex: "\\frac{x^{2}}{3}+5+z", + componentName: "/content1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1"].stateValues.latex)).eq( + "\\frac{x^{2}}{3}+5+z", + ); + expect(cleanLatex(stateVariables["/math2"].stateValues.latex)).eq( + "e^{-x^{2}}-a", + ); + }); + + it("math in graph, handle bad anchor coordinates", async () => { + let core = await createTestCore({ + doenetML: ` + + x^2 + + + +

Anchor 1 coordinates:

+

Change anchor 1 coordinates:

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "x", + ); + + // give good anchor coords + await updateMathInputValue({ + latex: "(6,7)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "(6,7)", + ); + + // give bad anchor coords again + await updateMathInputValue({ + latex: "q", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/math1anchor"].stateValues.latex)).eq( + "q", + ); + }); + + it("color math via style", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + +

Style number:

+ +

x^2 is $no_style.textStyleDescription, i.e., the text color is $no_style.textColor and the background color is $no_style.backgroundColor.

+

x^3 is $fixed_style.textStyleDescription, i.e., the text color is $fixed_style.textColor and the background color is $fixed_style.backgroundColor.

+

x^4 is $variable_style.textStyleDescription, i.e., the text color is $variable_style.textColor and the background color is $variable_style.backgroundColor.

+ + + $no_style{anchor="(1,2)"} + $fixed_style{anchor="(3,4)"} + $variable_style + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/tsd_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/tc_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/bc_no_style"].stateValues.text).eq("none"); + + expect(stateVariables["/tsd_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/tc_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/bc_fixed_style"].stateValues.text).eq("none"); + + expect(stateVariables["/tsd_variable_style"].stateValues.text).eq( + "black", + ); + expect(stateVariables["/tc_variable_style"].stateValues.text).eq( + "black", + ); + expect(stateVariables["/bc_variable_style"].stateValues.text).eq( + "none", + ); + + await updateMathInputValue({ latex: "2", componentName: "/sn", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/tsd_variable_style"].stateValues.text).eq( + "green", + ); + expect(stateVariables["/tc_variable_style"].stateValues.text).eq( + "green", + ); + expect(stateVariables["/bc_variable_style"].stateValues.text).eq( + "none", + ); + + expect(stateVariables["/tsd_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/tc_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/bc_no_style"].stateValues.text).eq("none"); + + expect(stateVariables["/tsd_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/tc_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/bc_fixed_style"].stateValues.text).eq("none"); + + await updateMathInputValue({ latex: "3", componentName: "/sn", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/tsd_variable_style"].stateValues.text).eq( + "red with a blue background", + ); + expect(stateVariables["/tc_variable_style"].stateValues.text).eq("red"); + expect(stateVariables["/bc_variable_style"].stateValues.text).eq( + "blue", + ); + + expect(stateVariables["/tsd_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/tc_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/bc_no_style"].stateValues.text).eq("none"); + + expect(stateVariables["/tsd_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/tc_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/bc_fixed_style"].stateValues.text).eq("none"); + }); + + it("math copied by plain macro, but not value, reflects style and anchor position", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + x^2 + x^3 + + + + + + + $m1{name="m1a"} + $m2{name="m2a"} + + + + + + $m1.value{assignNames="m1b"} + $m2.value{assignNames="m2b"} + + + + +

$m1{name="m1c"} $m2{name="m2c"}

+ +

$m1.value{assignNames="m1d"} $m2.value{assignNames="m2d"}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "^", + "x", + 2, + ]); + expect(stateVariables["/m1a"].stateValues.value.tree).eqls([ + "^", + "x", + 2, + ]); + expect(stateVariables["/m1b"].stateValues.value.tree).eqls([ + "^", + "x", + 2, + ]); + expect(stateVariables["/m1c"].stateValues.value.tree).eqls([ + "^", + "x", + 2, + ]); + expect(stateVariables["/m1d"].stateValues.value.tree).eqls([ + "^", + "x", + 2, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "^", + "x", + 3, + ]); + expect(stateVariables["/m2a"].stateValues.value.tree).eqls([ + "^", + "x", + 3, + ]); + expect(stateVariables["/m2b"].stateValues.value.tree).eqls([ + "^", + "x", + 3, + ]); + expect(stateVariables["/m2c"].stateValues.value.tree).eqls([ + "^", + "x", + 3, + ]); + expect(stateVariables["/m2d"].stateValues.value.tree).eqls([ + "^", + "x", + 3, + ]); + + expect(stateVariables["/m1"].stateValues.styleNumber).eq(2); + expect(stateVariables["/m1a"].stateValues.styleNumber).eq(2); + expect(stateVariables["/m1b"].stateValues.styleNumber).eq(1); + expect(stateVariables["/m1c"].stateValues.styleNumber).eq(2); + expect(stateVariables["/m1d"].stateValues.styleNumber).eq(1); + expect(stateVariables["/m2"].stateValues.styleNumber).eq(3); + expect(stateVariables["/m2a"].stateValues.styleNumber).eq(3); + expect(stateVariables["/m2b"].stateValues.styleNumber).eq(1); + expect(stateVariables["/m2c"].stateValues.styleNumber).eq(3); + expect(stateVariables["/m2d"].stateValues.styleNumber).eq(1); + + expect(cleanLatex(stateVariables["/m1coords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/m2coords"].stateValues.latex)).eq( + "(3,4)", + ); + expect(cleanLatex(stateVariables["/m1acoords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/m2acoords"].stateValues.latex)).eq( + "(3,4)", + ); + expect(cleanLatex(stateVariables["/m1bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/m2bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + + // move first maths + await core.requestAction({ + actionName: "moveMath", + componentName: "/m1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveMath", + componentName: "/m2", + args: { x: 4, y: -5 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1coords"].stateValues.latex)).eq( + "(-2,3)", + ); + expect(cleanLatex(stateVariables["/m2coords"].stateValues.latex)).eq( + "(4,-5)", + ); + expect(cleanLatex(stateVariables["/m1acoords"].stateValues.latex)).eq( + "(-2,3)", + ); + expect(cleanLatex(stateVariables["/m2acoords"].stateValues.latex)).eq( + "(4,-5)", + ); + expect(cleanLatex(stateVariables["/m1bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/m2bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + + // move second maths + await core.requestAction({ + actionName: "moveMath", + componentName: "/m1a", + args: { x: 7, y: 1 }, + event: null, + }); + await core.requestAction({ + actionName: "moveMath", + componentName: "/m2a", + args: { x: -8, y: 2 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1coords"].stateValues.latex)).eq( + "(7,1)", + ); + expect(cleanLatex(stateVariables["/m2coords"].stateValues.latex)).eq( + "(-8,2)", + ); + expect(cleanLatex(stateVariables["/m1acoords"].stateValues.latex)).eq( + "(7,1)", + ); + expect(cleanLatex(stateVariables["/m2acoords"].stateValues.latex)).eq( + "(-8,2)", + ); + expect(cleanLatex(stateVariables["/m1bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/m2bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + + // move third maths + await core.requestAction({ + actionName: "moveMath", + componentName: "/m1b", + args: { x: -6, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveMath", + componentName: "/m2b", + args: { x: -5, y: -4 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1coords"].stateValues.latex)).eq( + "(7,1)", + ); + expect(cleanLatex(stateVariables["/m2coords"].stateValues.latex)).eq( + "(-8,2)", + ); + expect(cleanLatex(stateVariables["/m1acoords"].stateValues.latex)).eq( + "(7,1)", + ); + expect(cleanLatex(stateVariables["/m2acoords"].stateValues.latex)).eq( + "(-8,2)", + ); + expect(cleanLatex(stateVariables["/m1bcoords"].stateValues.latex)).eq( + "(-6,3)", + ); + expect(cleanLatex(stateVariables["/m2bcoords"].stateValues.latex)).eq( + "(-5,-4)", + ); + }); + + it("vec", async () => { + let core = await createTestCore({ + doenetML: ` + \\vec{a} + vec a + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "\\vec{a}", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "\\vec{a}", + ); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls(["vec", "a"]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(["vec", "a"]); + }); + + it("line segment", async () => { + let core = await createTestCore({ + doenetML: ` + \\overline{AB} + linesegment(A,B) + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "\\overline{AB}", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "\\overline{AB}", + ); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "linesegment", + "A", + "B", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "linesegment", + "A", + "B", + ]); + }); + + it("perp", async () => { + let core = await createTestCore({ + doenetML: ` + v \\perp u + v perp u + v^\\perp + v^perp + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "v\\perpu", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "v\\perpu", + ); + expect(cleanLatex(stateVariables["/m3"].stateValues.latex)).eq( + "v^{\\perp}", + ); + expect(cleanLatex(stateVariables["/m4"].stateValues.latex)).eq( + "v^{\\perp}", + ); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "perp", + "v", + "u", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "perp", + "v", + "u", + ]); + expect(stateVariables["/m3"].stateValues.value.tree).eqls([ + "^", + "v", + "perp", + ]); + expect(stateVariables["/m4"].stateValues.value.tree).eqls([ + "^", + "v", + "perp", + ]); + }); + + it("parallel", async () => { + let core = await createTestCore({ + doenetML: ` + v \\parallel u + v parallel u + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + "v\\parallelu", + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + "v\\parallelu", + ); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "parallel", + "v", + "u", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "parallel", + "v", + "u", + ]); + }); + + it("basic units", async () => { + let core = await createTestCore({ + doenetML: ` +

+ $5 + 25% + 60 deg + \\$5 + 25\\% + 60^{\\circ} + $5 + 25% + sin(90 deg) +

+

+ $5 + 25% + 60 deg + sin(90 deg) +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/dol5"].stateValues.latex)).eq( + "\\$5", + ); + expect(cleanLatex(stateVariables["/perc25"].stateValues.latex)).eq( + "25\\%", + ); + expect(cleanLatex(stateVariables["/deg60"].stateValues.latex)).eq( + "60^{\\circ}", + ); + expect(cleanLatex(stateVariables["/dol5b"].stateValues.latex)).eq( + "\\$5", + ); + expect(cleanLatex(stateVariables["/perc25b"].stateValues.latex)).eq( + "25\\%", + ); + expect(cleanLatex(stateVariables["/deg60b"].stateValues.latex)).eq( + "60^{\\circ}", + ); + expect(cleanLatex(stateVariables["/dol5c"].stateValues.latex)).eq( + "\\$5", + ); + expect(cleanLatex(stateVariables["/perc25c"].stateValues.latex)).eq( + "25\\%", + ); + expect(cleanLatex(stateVariables["/sin90deg"].stateValues.latex)).eq( + "\\sin(90^{\\circ})", + ); + + expect(stateVariables["/ndol5"].stateValues.text).eq("5"); + expect(stateVariables["/nperc25"].stateValues.text).eq("0.25"); + expect(parseFloat(stateVariables["/ndeg60"].stateValues.text)).closeTo( + Math.PI / 3, + 1e-2, + ); + expect(stateVariables["/nsin90deg"].stateValues.text).eq("1"); + + expect(stateVariables["/dol5"].stateValues.value.tree).eqls([ + "unit", + "$", + 5, + ]); + expect(stateVariables["/perc25"].stateValues.value.tree).eqls([ + "unit", + 25, + "%", + ]); + expect(stateVariables["/deg60"].stateValues.value.tree).eqls([ + "unit", + 60, + "deg", + ]); + expect(stateVariables["/dol5b"].stateValues.value.tree).eqls([ + "unit", + "$", + 5, + ]); + expect(stateVariables["/perc25b"].stateValues.value.tree).eqls([ + "unit", + 25, + "%", + ]); + expect(stateVariables["/deg60b"].stateValues.value.tree).eqls([ + "unit", + 60, + "deg", + ]); + expect(stateVariables["/dol5c"].stateValues.value.tree).eqls([ + "unit", + "$", + 5, + ]); + expect(stateVariables["/perc25c"].stateValues.value.tree).eqls([ + "unit", + 25, + "%", + ]); + expect(stateVariables["/ndol5"].stateValues.value).eq(5); + expect(stateVariables["/nperc25"].stateValues.value).eq(0.25); + expect(stateVariables["/ndeg60"].stateValues.value).closeTo( + Math.PI / 3, + 1e-14, + ); + expect(stateVariables["/nsin90deg"].stateValues.value).eq(1); + }); + + it("some support for integral", async () => { + let core = await createTestCore({ + doenetML: ` +

+ int f(x) dx + int_a^b f(x) dx + \\int f(x) dx + \\int_a^b f(x) dx +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/indefint"].stateValues.latex)).eq( + "\\intf(x)dx", + ); + expect(cleanLatex(stateVariables["/defint"].stateValues.latex)).eq( + "\\int_{a}^{b}f(x)dx", + ); + expect(cleanLatex(stateVariables["/indefintb"].stateValues.latex)).eq( + "\\intf(x)dx", + ); + expect(cleanLatex(stateVariables["/defintb"].stateValues.latex)).eq( + "\\int_{a}^{b}f(x)dx", + ); + }); + + it("recover math values through latex state variables", async () => { + let core = await createTestCore({ + doenetML: ` +

+ (3,4) + (5,6) + sin(x)/exp(x) + \\frac{x}{y} + y/z + y=x+4 + sin(x)cos(x) + tan(x) cot(y) +

+

+ $v.latex + $p.latex + $f.latex + $m.latex + $math.latex + $l.latex + $al.latex + $ml.latex +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/v2"].stateValues.value.tree).eqls([ + "tuple", + 3, + 4, + ]); + expect(stateVariables["/p2"].stateValues.value.tree).eqls([ + "tuple", + 5, + 6, + ]); + expect(stateVariables["/f2"].stateValues.value.tree).eqls([ + "/", + ["apply", "sin", "x"], + ["apply", "exp", "x"], + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "/", + "x", + "y", + ]); + expect(stateVariables["/math2"].stateValues.value.tree).eqls([ + "/", + "y", + "z", + ]); + expect(stateVariables["/l2"].stateValues.value.tree).eqls([ + "=", + "y", + ["+", "x", 4], + ]); + expect(stateVariables["/al2"].stateValues.value.tree).eqls([ + "list", + ["apply", "sin", "x"], + ["apply", "cos", "x"], + ]); + expect(stateVariables["/ml2"].stateValues.value.tree).eqls([ + "list", + ["apply", "tan", "x"], + ["apply", "cot", "y"], + ]); + }); + + it("Don't divide by vectors when inverting math", async () => { + let core = await createTestCore({ + doenetML: ` + 3 + $n(3,4) + + + 3 + $n2*4 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/n2"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "tuple", + 9, + 12, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(12); + + await updateMathInputValue({ + latex: "(6,8)", + componentName: "/mi", + core, + }); + await updateMathInputValue({ latex: "8", componentName: "/mi2", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/n2"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "tuple", + 9, + 12, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(8); + }); + + it("support for some logical operators", async () => { + let core = await createTestCore({ + doenetML: ` +

+ not a + !a + \\lnot a + \\neg a + !a +

+

+ a implies b + a β‡’ b + a ⟹ b + a \\implies b + a \\Longrightarrow b + a \\Rightarrow b +

+ +

+ a impliedby b + a ⇐ b + a ⟸ b + a \\impliedby b + a \\Longleftarrow b + a \\Leftarrow b +

+ +

+ a iff b + a ⇔ b + a ⟺ b + a \\iff b + a \\Longleftrightarrow b + a \\Leftrightarrow b +

+ +

+ a rightarrow b + a β†’ b + a ⟢ b + a \\to b + a \\longrightarrow b + a \\rightarrow b +

+ +

+ a leftarrow b + a ← b + a ⟡ b + a \\gets b + a \\longleftarrow b + a \\leftarrow b +

+ +

+ a leftrightarrow b + a ↔ b + a ⟷ b + a \\longleftrightarrow b + a \\leftrightarrow b +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let nots = ["/not_a", "/not_b", "/not_c", "/not_d", "/not_e"]; + let implies = [ + "/implies_a", + "/implies_b", + "/implies_c", + "/implies_d", + "/implies_e", + "/implies_f", + ]; + let impliedby = [ + "/impliedby_a", + "/impliedby_b", + "/impliedby_c", + "/impliedby_d", + "/impliedby_e", + "/impliedby_f", + ]; + let iff = ["/iff_a", "/iff_b", "/iff_c", "/iff_d", "/iff_e", "/iff_f"]; + + let rightarrow = [ + "/rightarrow_a", + "/rightarrow_b", + "/rightarrow_c", + "/rightarrow_d", + "/rightarrow_e", + "/rightarrow_f", + ]; + let leftarrow = [ + "/leftarrow_a", + "/leftarrow_b", + "/leftarrow_c", + "/leftarrow_d", + "/leftarrow_e", + "/leftarrow_f", + ]; + let leftrightarrow = [ + "/leftrightarrow_a", + "/leftrightarrow_b", + "/leftrightarrow_c", + "/leftrightarrow_d", + "/leftrightarrow_e", + ]; + + for (let id of nots) { + expect(stateVariables[id].stateValues.value.tree).eqls([ + "not", + "a", + ]); + } + for (let id of implies) { + expect(stateVariables[id].stateValues.value.tree).eqls([ + "implies", + "a", + "b", + ]); + } + for (let id of impliedby) { + expect(stateVariables[id].stateValues.value.tree).eqls([ + "impliedby", + "a", + "b", + ]); + } + for (let id of iff) { + expect(stateVariables[id].stateValues.value.tree).eqls([ + "iff", + "a", + "b", + ]); + } + for (let id of rightarrow) { + expect(stateVariables[id].stateValues.value.tree).eqls([ + "rightarrow", + "a", + "b", + ]); + } + for (let id of leftarrow) { + expect(stateVariables[id].stateValues.value.tree).eqls([ + "leftarrow", + "a", + "b", + ]); + } + for (let id of leftrightarrow) { + expect(stateVariables[id].stateValues.value.tree).eqls([ + "leftrightarrow", + "a", + "b", + ]); + } + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/mathinput.test.ts b/packages/doenetml-worker/src/test/tagSpecific/mathinput.test.ts new file mode 100644 index 000000000..6c8179b2a --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/mathinput.test.ts @@ -0,0 +1,9225 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputImmediateValue, + updateMathInputValue, + updateMathInputValueToImmediateValue, + updateMatrixInputValue, + updateTextInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("MathInput tag tests", async () => { + it("mathInput references", async () => { + // A fairly involved test + // to check for bugs that have shown up after multiple manipulations + + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+1"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x+1"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq(""); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).to.eq("\uFF3F"); + + // Type 2 in first mathInput + await updateMathInputImmediateValue({ + latex: "x+12", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+12"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x+12"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq(""); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).to.eq("\uFF3F"); + + // Changing to 3 in first mathInput + await updateMathInputImmediateValue({ + latex: "x+1", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "x+13", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+13"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x+13"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq(""); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 13, + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 13, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).to.eq("\uFF3F"); + + // Update value (e.g., by pressing Enter) in first mathInput + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+13"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x+13"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq(""); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 13, + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 13, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 13, + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + 13, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).to.eq("\uFF3F"); + + // Erasing 13 and typing y second mathInput + await updateMathInputImmediateValue({ + latex: "x+1", + componentName: "/mi1a", + core, + }); + await updateMathInputImmediateValue({ + latex: "x+", + componentName: "/mi1a", + core, + }); + await updateMathInputImmediateValue({ + latex: "x+y", + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+y"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x+y"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq(""); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 13, + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + 13, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).to.eq("\uFF3F"); + + // Update value (e.g., by changing focus) of second mathInput + await updateMathInputValueToImmediateValue({ + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+y"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x+y"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq(""); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).to.eq("\uFF3F"); + + // Typing pq in third mathInput + await updateMathInputImmediateValue({ + latex: "p", + componentName: "/mi2", + core, + }); + await updateMathInputImmediateValue({ + latex: "pq", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+y"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x+y"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("pq"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "p", + "q", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).to.eq("\uFF3F"); + + // update value (e.g., press enter) in mathInput 3 + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+y"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x+y"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("pq"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "p", + "q", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "p", + "q", + ]); + + // type abc in mathInput 2 + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi1a", + core, + }); + await updateMathInputImmediateValue({ + latex: "a", + componentName: "/mi1a", + core, + }); + await updateMathInputImmediateValue({ + latex: "ab", + componentName: "/mi1a", + core, + }); + await updateMathInputImmediateValue({ + latex: "abc", + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("abc"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("abc"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("pq"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "p", + "q", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "p", + "q", + ]); + + // update value (e.g., blur) mathInput 2 + await updateMathInputValueToImmediateValue({ + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("abc"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("abc"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("pq"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "p", + "q", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "p", + "q", + ]); + + // delete and reenter abc in mathInput 1 + + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq(""); + + await updateMathInputImmediateValue({ + latex: "a", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "ab", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "abc", + componentName: "/mi1", + core, + }); + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("abc"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("abc"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("pq"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "p", + "q", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "p", + "q", + ]); + + // type u/v in mathInput 3 + + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi2", + core, + }); + await updateMathInputImmediateValue({ + latex: "u", + componentName: "/mi2", + core, + }); + await updateMathInputImmediateValue({ + latex: "u/", + componentName: "/mi2", + core, + }); + await updateMathInputImmediateValue({ + latex: "u/v", + componentName: "/mi2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("abc"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("abc"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("u/v"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "/", + "u", + "v", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "p", + "q", + ]); + + // blue mathInput 2 and type d in mathInput 1 + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + + await updateMathInputImmediateValue({ + latex: "abcd", + componentName: "/mi1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("abcd"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("abcd"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("u/v"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + "d", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + "d", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "/", + "u", + "v", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "/", + "u", + "v", + ]); + + // Update value (e.g., blur) first mathInput + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("abcd"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("abcd"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("u/v"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + "d", + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + "c", + "d", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "/", + "u", + "v", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + "d", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + "d", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "/", + "u", + "v", + ]); + + // Clearing second mathInput + + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi1a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq(""); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq(""); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("u/v"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "/", + "u", + "v", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + "d", + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + "c", + "d", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "/", + "u", + "v", + ]); + + // update value (e.g., by blurring) of second mathInput + + await updateMathInputValueToImmediateValue({ + componentName: "/mi1a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq(""); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq(""); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("u/v"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).to.eq( + "\uFF3F", + ); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "/", + "u", + "v", + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).to.eq("\uFF3F"); + expect(stateVariables["/mi1a"].stateValues.value.tree).to.eq("\uFF3F"); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "/", + "u", + "v", + ]); + }); + + it("mathinput references with invalid math expressions", async () => { + let doenetML = ` + + + `; + + let core = await createTestCore({ + doenetML, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq(""); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq(""); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls( + "οΌΏ", + ); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls( + "οΌΏ", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("οΌΏ"); + + // Type x~ in first mathinput + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "x~", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x~"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x~"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls( + "οΌΏ", + ); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls( + "οΌΏ", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("οΌΏ"); + + // Delete ~ and add -y in copied mathinput + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi1a", + core, + }); + await updateMathInputImmediateValue({ + latex: "x-", + componentName: "/mi1a", + core, + }); + await updateMathInputImmediateValue({ + latex: "x-y", + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("οΌΏ"); + + // update value (e.g., blur) + await updateMathInputValueToImmediateValue({ + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + + // Add & in copied mathinput + await updateMathInputImmediateValue({ + latex: "x-y@", + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y@"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y@"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls( + "οΌΏ", + ); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls( + "οΌΏ", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + + // Delete @ and add *z in first mathinput + await updateMathInputValueToImmediateValue({ + componentName: "/mi1a", + core, + }); + + await updateMathInputImmediateValue({ + latex: "x-y", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "x-y*", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "x-y*z", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y*z"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y*z"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("οΌΏ"); + + // Update value (e.g., press enter) + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y*z"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y*z"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + }); + + it("mathinput references with incomplete math expressions", async () => { + let doenetML = ` + + + + + + +

$bi.value{assignNames="b"}

+ `; + + let core = await createTestCore({ + doenetML, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq(""); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq(""); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls( + "οΌΏ", + ); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls( + "οΌΏ", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("οΌΏ"); + + // Type x- in first mathinput + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "x-", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls( + "x-", + ); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls( + "x-", + ); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("x-"); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("x-"); + + // Add y in copied mathinput + await updateMathInputImmediateValue({ + latex: "x-y", + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("x-"); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("x-"); + + // update value (e.g., blur) + await updateMathInputValueToImmediateValue({ + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + + // Add * in copied mathinput + await updateMathInputImmediateValue({ + latex: "x-y*", + componentName: "/mi1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y*"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y*"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "οΌΏ"]], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "οΌΏ"]], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", "y"], + ]); + + // Add z in first mathinput + await updateMathInputValueToImmediateValue({ + componentName: "/mi1a", + core, + }); + await updateMathInputImmediateValue({ + latex: "x-y*z", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y*z"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y*z"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "οΌΏ"]], + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "οΌΏ"]], + ]); + + // Update value (e.g., press enter) + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x-y*z"); + expect( + cleanLatex(stateVariables["/mi1a"].stateValues.rawRendererValue), + ).eq("x-y*z"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1a"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + expect(stateVariables["/mi1a"].stateValues.value.tree).eqls([ + "+", + "x", + ["-", ["*", "y", "z"]], + ]); + }); + + it("downstream from mathinput", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: 1+2x

+

MathInput based on math:

+

Copied mathinput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("1+2x"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("1+2x"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + + // type new values + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "xy", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("xy"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("xy"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + + // press enter + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("xy"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("xy"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + + // enter new values in referenced + await updateMathInputValue({ + latex: "qr", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("qr"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("qr"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + }); + + it("downstream from mathinput, prefill ignored", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: 1+2x

+

MathInput based on math:

+

Copied mathinput:

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("1+2x"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("1+2x"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + }); + + it("downstream from mathinput, normal downstream rules apply", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: 1+3x

+

MathInput based on math:

+

Copied mathinput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("3x+1"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("3x+1"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/_math2"].stateValues.value.tree).eqls([ + "*", + 3, + "x", + ]); + + // type new values + await updateMathInputValue({ + latex: "xy", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("xy"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("xy"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/_math2"].stateValues.value.tree).eqls([ + "+", + ["*", "x", "y"], + -1, + ]); + + // enter new values in reffed + await updateMathInputValue({ + latex: "qr", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("qr"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("qr"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/_math2"].stateValues.value.tree).eqls([ + "+", + ["*", "q", "r"], + -1, + ]); + }); + + it("downstream from mathinput via child", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: 1+2x

+

MathInput based on math: $_math1

+

Copied mathinput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("1+2x"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("1+2x"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + + // type new values + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi1", + core, + }); + await updateMathInputImmediateValue({ + latex: "xy", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("xy"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("xy"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + + // press enter + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("xy"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("xy"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + + // enter new values in referenced + await updateMathInputValue({ + latex: "qr", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("qr"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("qr"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + }); + + it("downstream from mathinput via child, prefill ignored", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: 1+2x

+

MathInput based on math: $_math1

+

Copied mathinput:

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("1+2x"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("1+2x"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x"], + ]); + }); + + it("combination children including string", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: x

+

MathInput based on math and strings: 2$_math1+1

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("2x+1"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + 1, + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + ["*", 2, "x"], + 1, + ]); + + // type in new values + await updateMathInputValue({ + latex: "2y+1", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("2y+1"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "y"], + 1, + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls("y"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + ["*", 2, "y"], + 1, + ]); + }); + + it("child overrides bindValueTo", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: x

+

MathInput with child and bindValueTo: y

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("y"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("y"); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls( + "y", + ); + + // type in new values + await updateMathInputValue({ + latex: "2z", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("2z"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + 2, + "z", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + 2, + "z", + ]); + }); + + it("downstream from mathinput via child, normal downstream rules apply", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: 1+3x

+

MathInput based on math: $_math1

+

Copied mathinput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("3x+1"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("3x+1"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + 1, + ]); + expect(stateVariables["/_math2"].stateValues.value.tree).eqls([ + "*", + 3, + "x", + ]); + + // type new values + await updateMathInputValue({ + latex: "xy", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("xy"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("xy"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/_math2"].stateValues.value.tree).eqls([ + "+", + ["*", "x", "y"], + -1, + ]); + + // enter new values in reffed + await updateMathInputValue({ + latex: "qr", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("qr"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("qr"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/_math2"].stateValues.value.tree).eqls([ + "+", + ["*", "q", "r"], + -1, + ]); + }); + + it("values revert if bind to value that is not updatable", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: 1+2xz

+

MathInput based on math:

+

Copied mathinput:

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("1+2xz"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("1+2xz"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + + // type new values + await updateMathInputImmediateValue({ + latex: "xy", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("xy"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("xy"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + + // value revert when updateValue (e.g., press enter) + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("1+2xz"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("1+2xz"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + + // type new values in copy + + await updateMathInputImmediateValue({ + latex: "qr", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("qr"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("qr"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "*", + "q", + "r", + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + + // values revert when update value (e.g., blur) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("1+2xz"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("1+2xz"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 1, + ["*", 2, "x", "z"], + ]); + }); + + it("values revert if bind to fixed value", async () => { + let core = await createTestCore({ + doenetML: ` +

Original math: x

+

MathInput based on math:

+

Copied mathinput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq("x"); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq("x"); + expect(stateVariables["/_math1"].stateValues.value.tree).eq("x"); + + // type new values + await updateMathInputImmediateValue({ + latex: "y", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("y"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("y"); + expect(stateVariables["/mi1"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq("y"); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq("y"); + expect(stateVariables["/_math1"].stateValues.value.tree).eq("x"); + + // value revert when update value (e.g., press enter) + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x"); + + expect(stateVariables["/mi1"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq("x"); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq("x"); + expect(stateVariables["/_math1"].stateValues.value.tree).eq("x"); + + // type new values in copy + await updateMathInputImmediateValue({ + latex: "z", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("z"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("z"); + expect(stateVariables["/mi1"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq("z"); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq("z"); + expect(stateVariables["/_math1"].stateValues.value.tree).eq("x"); + + // values revert when update value (e.g., blur) + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x"); + expect(stateVariables["/mi1"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq("x"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq("x"); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq("x"); + expect(stateVariables["/_math1"].stateValues.value.tree).eq("x"); + }); + + it("mathinput based on value of mathinput", async () => { + let core = await createTestCore({ + doenetML: ` +

Original mathinput:

+

mathinput based on mathinput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+1"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+1"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + + // type 2 in first mathinput + await updateMathInputImmediateValue({ + latex: "x+12", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+12"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+1"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + + // update value (e.g., press enter) + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+12"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+12"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + + // type 3 in second mathinput + await updateMathInputImmediateValue({ + latex: "x+123", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+12"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+123"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 123, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + + // update value (e.g., blur) + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+123"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+123"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 123, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 123, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 123, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 123, + ]); + }); + + it("mathinput based on immediate value of mathinput", async () => { + let core = await createTestCore({ + doenetML: ` +

Original mathinput:

+

mathinput based on mathinput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+1"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+1"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + + // type 2 in first mathinput + await updateMathInputImmediateValue({ + latex: "x+12", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+12"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+12"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 1, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + + // update value (e.g., press enter) + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+12"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+12"); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + + // type 3 in second mathinput + await updateMathInputImmediateValue({ + latex: "x+123", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+12"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+123"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 123, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 12, + ]); + + // update value (e.g., blur) + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("x+123"); + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("x+123"); + + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 123, + ]); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + "x", + 123, + ]); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eqls([ + "+", + "x", + 123, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + "x", + 123, + ]); + }); + + it("accurately reduce vector length", async () => { + let core = await createTestCore({ + doenetML: ` + Enter vector + + + `, + }); + + // verify fixed bug where didn't reduce size of a vector + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq(""); + + await updateMathInputValue({ + latex: "(1,2,3)", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "(1,2,3)", + ); + + await updateMathInputValue({ + latex: "(2,3)", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq("(2,3)"); + }); + + it("function symbols", async () => { + let core = await createTestCore({ + doenetML: ` +

f, g:

+

+ +

h, q:

+

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a2"].stateValues.value.tree).eqls("\uff3f"); + expect(stateVariables["/b2"].stateValues.value.tree).eqls("\uff3f"); + + await updateMathInputValue({ + latex: "f(x)", + componentName: "/a", + core, + }); + await updateMathInputValue({ + latex: "f(x)", + componentName: "/b", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "f", + "x", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "f", + "x", + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + "f", + "x", + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + "f", + "x", + ]); + + await updateMathInputValue({ + latex: "g(f)", + componentName: "/a", + core, + }); + await updateMathInputValue({ + latex: "g(f)", + componentName: "/b", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "g", + "f", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "g", + "f", + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + "g", + "f", + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + "g", + "f", + ]); + + await updateMathInputValue({ + latex: "h(q)", + componentName: "/a", + core, + }); + await updateMathInputValue({ + latex: "h(q)", + componentName: "/b", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + "h", + "q", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + "h", + "q", + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "apply", + "h", + "q", + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "apply", + "h", + "q", + ]); + + await updateMathInputValue({ + latex: "q(z)", + componentName: "/a", + core, + }); + await updateMathInputValue({ + latex: "q(z)", + componentName: "/b", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + "q", + "z", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + "q", + "z", + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "apply", + "q", + "z", + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "apply", + "q", + "z", + ]); + }); + + it("display digits", async () => { + let core = await createTestCore({ + doenetML: ` + a +

a:

+

a2:

+

a3:

+

a4:

+

a5:

+ +

b: 10e^(3y)

+

b2:

+

b3:

+

b4:

+

b5:

+

b6:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(2x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("10e^{3y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/b5"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/b6"].stateValues.latex)).eq( + "10e^{3y}", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a4"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a4"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a5"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a5"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b5"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b5"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b6"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b6"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + + await updateMathInputImmediateValue({ + latex: "\\sin(345.15389319x)", + componentName: "/a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(345.15389319x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(345.15x)", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq( + "\\sin(2x)", + ); + + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq( + "\\sin(345.15389319x)", + ); + + await updateMathInputValueToImmediateValue({ + componentName: "/a", + core, + }); + await updateMathInputImmediateValue({ + latex: "2.047529344518e^{0.0000073013048309y}", + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(345.15x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(345.15x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(345.15x)", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq( + "\\sin(345.15389319x)", + ); + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq( + "\\sin(345.15389319x)", + ); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("2.047529344518e^{0.0000073013048309y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "2.05e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b5"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/b6"].stateValues.latex)).eq( + "2.047529344518e^{0.0000073013048309y}", + ); + + await updateMathInputValueToImmediateValue({ + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "2.047529345e^{0.000007301304831y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("2.05e^{0.0000073y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "2.05e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "2.05e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b5"].stateValues.latex)).eq( + "2.047529344518e^{0.0000073013048309y}", + ); + expect(cleanLatex(stateVariables["/b6"].stateValues.latex)).eq( + "2.047529344518e^{0.0000073013048309y}", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a4"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a4"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a5"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a5"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b5"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b5"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b6"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b6"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + + await updateMathInputImmediateValue({ + latex: "\\sin(345.14x)", + componentName: "/a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(345.14x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(345.15x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq( + "\\sin(345.15389319x)", + ); + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a4"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a4"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a5"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a5"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + + await updateMathInputValueToImmediateValue({ + componentName: "/a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(345.14x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a4"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a4"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a5"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a5"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + + await updateMathInputImmediateValue({ + latex: "6.05e^{0.0000073y}", + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "2.047529345e^{0.000007301304831y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("6.05e^{0.0000073y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "2.05e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "6.05e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b5"].stateValues.latex)).eq( + "2.047529344518e^{0.0000073013048309y}", + ); + expect(cleanLatex(stateVariables["/b6"].stateValues.latex)).eq( + "6.05e^{0.0000073y}", + ); + + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b5"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b5"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b6"].stateValues.value.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b6"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + + await updateMathInputValueToImmediateValue({ + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "6.05e^{0.0000073y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("6.05e^{0.0000073y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "6.05e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "6.05e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b5"].stateValues.latex)).eq( + "6.05e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b6"].stateValues.latex)).eq( + "6.05e^{0.0000073y}", + ); + + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b5"].stateValues.value.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b5"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b6"].stateValues.value.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b6"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.05, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + }); + + it("display decimals", async () => { + let core = await createTestCore({ + doenetML: ` +

a:

+

a2:

+

a3:

+ +

b: 10e^(3y)

+

b2:

+

b3:

+

b4:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(2x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("10e^{3y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "10e^{3y}", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + + await updateMathInputImmediateValue({ + latex: "\\sin(345.15389319x)", + componentName: "/a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(345.15389319x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(345.15x)", + ); + + await updateMathInputValueToImmediateValue({ + componentName: "/a", + core, + }); + await updateMathInputImmediateValue({ + latex: "2.047529344518e^{0.0000073013048309y}", + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(345.15x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(345.15x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(345.15x)", + ); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("2.047529344518e^{0.0000073013048309y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "2.04752934e^{0.0000073y}", + ); + + await updateMathInputValueToImmediateValue({ + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "2.047529345e^{0.000007301304831y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("2.04752934e^{0.0000073y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "2.04752934e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "2.04752934e^{0.0000073y}", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + + await updateMathInputImmediateValue({ + latex: "\\sin(345.14x)", + componentName: "/a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(345.14x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(345.15x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.15389319, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.15, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + + await updateMathInputValueToImmediateValue({ + componentName: "/a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(345.14x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(345.14x)", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 345.14, "x"], + ]); + + await updateMathInputImmediateValue({ + latex: "6.04752934e^{0.0000073y}", + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "2.047529345e^{0.000007301304831y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("6.04752934e^{0.0000073y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "2.04752934e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "6.04752934e^{0.0000073y}", + ); + + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 2.047529344518, + ["^", "e", ["*", 0.0000073013048309, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 2.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + + await updateMathInputValueToImmediateValue({ + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "6.04752934e^{0.0000073y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("6.04752934e^{0.0000073y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "6.04752934e^{0.0000073y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "6.04752934e^{0.0000073y}", + ); + + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.04752934, + ["^", "e", ["*", 0.0000073, "y"]], + ]); + }); + + it("display small as zero", async () => { + let core = await createTestCore({ + doenetML: ` + a +

a:

+

a2:

+

a3:

+ +

b: 10e^(3y)

+

b2:

+

b3:

+

b4:

+ +

c:

+

c2:

+

c3:

+ +

d: 10e^(3y)

+

d2:

+

d3:

+

d4:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(2x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("10e^{3y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect( + cleanLatex(stateVariables["/c"].stateValues.rawRendererValue), + ).eq("\\sin(2x)"); + expect(cleanLatex(stateVariables["/c2"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/c3"].stateValues.latex)).eq( + "\\sin(2x)", + ); + expect(cleanLatex(stateVariables["/d"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect( + cleanLatex(stateVariables["/d2"].stateValues.rawRendererValue), + ).eq("10e^{3y}"); + expect(cleanLatex(stateVariables["/d3"].stateValues.latex)).eq( + "10e^{3y}", + ); + expect(cleanLatex(stateVariables["/d4"].stateValues.latex)).eq( + "10e^{3y}", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/c"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/c"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/c2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/c2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/c3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/c3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/d"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/d2"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/d2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/d3"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/d3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/d4"].stateValues.value.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + expect(stateVariables["/d4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 10, + ["^", "e", ["*", 3, "y"]], + ]); + + await updateMathInputValue({ + latex: "\\sin(0.000000000000000472946384739473x)", + componentName: "/a", + core, + }); + await updateMathInputValue({ + latex: "0.0000000000000934720357236e^{0.0000000000000073013048309y}", + componentName: "/b2", + core, + }); + await updateMathInputValue({ + latex: "\\sin(0.000000000000000472946384739473x)", + componentName: "/c", + core, + }); + await updateMathInputValue({ + latex: "0.0000000000000934720357236e^{0.0000000000000073013048309y}", + componentName: "/d2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(4.7295\\cdot10^{-16}x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(4.7295\\cdot10^{-16}x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(4.7295\\cdot10^{-16}x)", + ); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "9.347203572\\cdot10^{-14}e^{7.301304831\\cdot10^{-15}y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("9.35\\cdot10^{-14}e^{7.3\\cdot10^{-15}y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "9.35\\cdot10^{-14}e^{7.3\\cdot10^{-15}y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "9.35\\cdot10^{-14}e^{7.3\\cdot10^{-15}y}", + ); + expect( + cleanLatex(stateVariables["/c"].stateValues.rawRendererValue), + ).eq("\\sin(0x)"); + expect(cleanLatex(stateVariables["/c2"].stateValues.latex)).eq( + "\\sin(0x)", + ); + expect(cleanLatex(stateVariables["/c3"].stateValues.latex)).eq( + "\\sin(0x)", + ); + expect(cleanLatex(stateVariables["/d"].stateValues.latex)).eq( + "9.347203572\\cdot10^{-14}e^{7.301304831\\cdot10^{-15}y}", + ); + expect( + cleanLatex(stateVariables["/d2"].stateValues.rawRendererValue), + ).eq("9.35\\cdot10^{-14}e^{0y}"); + expect(cleanLatex(stateVariables["/d3"].stateValues.latex)).eq( + "9.35\\cdot10^{-14}e^{0y}", + ); + expect(cleanLatex(stateVariables["/d4"].stateValues.latex)).eq( + "9.35\\cdot10^{-14}e^{0y}", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 4.72946384739473e-16, "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 4.7295e-16, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 4.72946384739473e-16, "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 4.7295e-16, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 4.72946384739473e-16, "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 4.7295e-16, "x"], + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 9.34720357236e-14, + ["^", "e", ["*", 7.3013048309e-15, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 9.34720357236e-14, + ["^", "e", ["*", 7.3013048309e-15, "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 9.35e-14, + ["^", "e", ["*", 7.3e-15, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 9.34720357236e-14, + ["^", "e", ["*", 7.3013048309e-15, "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 9.35e-14, + ["^", "e", ["*", 7.3e-15, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 9.34720357236e-14, + ["^", "e", ["*", 7.3013048309e-15, "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 9.35e-14, + ["^", "e", ["*", 7.3e-15, "y"]], + ]); + expect(stateVariables["/c"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 4.72946384739473e-16, "x"], + ]); + expect(stateVariables["/c"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 0, "x"], + ]); + expect(stateVariables["/c2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 4.72946384739473e-16, "x"], + ]); + expect(stateVariables["/c2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 0, "x"], + ]); + expect(stateVariables["/c3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 4.72946384739473e-16, "x"], + ]); + expect(stateVariables["/c3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 0, "x"], + ]); + expect(stateVariables["/d"].stateValues.value.tree).eqls([ + "*", + 9.34720357236e-14, + ["^", "e", ["*", 7.3013048309e-15, "y"]], + ]); + expect(stateVariables["/d2"].stateValues.value.tree).eqls([ + "*", + 9.34720357236e-14, + ["^", "e", ["*", 7.3013048309e-15, "y"]], + ]); + expect(stateVariables["/d2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 9.35e-14, + ["^", "e", ["*", 0, "y"]], + ]); + expect(stateVariables["/d3"].stateValues.value.tree).eqls([ + "*", + 9.34720357236e-14, + ["^", "e", ["*", 7.3013048309e-15, "y"]], + ]); + expect(stateVariables["/d3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 9.35e-14, + ["^", "e", ["*", 0, "y"]], + ]); + expect(stateVariables["/d4"].stateValues.value.tree).eqls([ + "*", + 9.34720357236e-14, + ["^", "e", ["*", 7.3013048309e-15, "y"]], + ]); + expect(stateVariables["/d4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 9.35e-14, + ["^", "e", ["*", 0, "y"]], + ]); + + await updateMathInputValue({ + latex: "\\sin(5.7295\\cdot10^{-16}x)", + componentName: "/a", + core, + }); + await updateMathInputValue({ + latex: "8.35\\cdot10^{-14}e^{7.3\\cdot10^{-15}y}", + componentName: "/b2", + core, + }); + await updateMathInputValue({ + latex: "\\sin(30x)", + componentName: "/c", + core, + }); + await updateMathInputValue({ + latex: "6.35\\cdot10^{-14}e^{0y}", + componentName: "/d2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\sin(5.7295\\cdot10^{-16}x)"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\sin(5.7295\\cdot10^{-16}x)", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\sin(5.7295\\cdot10^{-16}x)", + ); + expect(cleanLatex(stateVariables["/b"].stateValues.latex)).eq( + "8.35\\cdot10^{-14}e^{7.3\\cdot10^{-15}y}", + ); + expect( + cleanLatex(stateVariables["/b2"].stateValues.rawRendererValue), + ).eq("8.35\\cdot10^{-14}e^{7.3\\cdot10^{-15}y}"); + expect(cleanLatex(stateVariables["/b3"].stateValues.latex)).eq( + "8.35\\cdot10^{-14}e^{7.3\\cdot10^{-15}y}", + ); + expect(cleanLatex(stateVariables["/b4"].stateValues.latex)).eq( + "8.35\\cdot10^{-14}e^{7.3\\cdot10^{-15}y}", + ); + expect( + cleanLatex(stateVariables["/c"].stateValues.rawRendererValue), + ).eq("\\sin(30x)"); + expect(cleanLatex(stateVariables["/c2"].stateValues.latex)).eq( + "\\sin(30x)", + ); + expect(cleanLatex(stateVariables["/c3"].stateValues.latex)).eq( + "\\sin(30x)", + ); + expect(cleanLatex(stateVariables["/d"].stateValues.latex)).eq( + "6.35\\cdot10^{-14}e^{0y}", + ); + expect( + cleanLatex(stateVariables["/d2"].stateValues.rawRendererValue), + ).eq("6.35\\cdot10^{-14}e^{0y}"); + expect(cleanLatex(stateVariables["/d3"].stateValues.latex)).eq( + "6.35\\cdot10^{-14}e^{0y}", + ); + expect(cleanLatex(stateVariables["/d4"].stateValues.latex)).eq( + "6.35\\cdot10^{-14}e^{0y}", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 5.7295, ["^", 10, -16], "x"], + ]); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 5.7295, ["^", 10, -16], "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 5.7295, ["^", 10, -16], "x"], + ]); + expect(stateVariables["/a2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 5.7295, ["^", 10, -16], "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 5.7295, ["^", 10, -16], "x"], + ]); + expect(stateVariables["/a3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 5.7295, ["^", 10, -16], "x"], + ]); + expect(stateVariables["/b"].stateValues.value.tree).eqls([ + "*", + 8.35, + ["^", 10, -14], + ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], + ]); + expect(stateVariables["/b2"].stateValues.value.tree).eqls([ + "*", + 8.35, + ["^", 10, -14], + ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], + ]); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 8.35, + ["^", 10, -14], + ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], + ]); + expect(stateVariables["/b3"].stateValues.value.tree).eqls([ + "*", + 8.35, + ["^", 10, -14], + ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], + ]); + expect(stateVariables["/b3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 8.35, + ["^", 10, -14], + ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], + ]); + expect(stateVariables["/b4"].stateValues.value.tree).eqls([ + "*", + 8.35, + ["^", 10, -14], + ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], + ]); + expect(stateVariables["/b4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 8.35, + ["^", 10, -14], + ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], + ]); + expect(stateVariables["/c"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 30, "x"], + ]); + expect(stateVariables["/c"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 30, "x"], + ]); + expect(stateVariables["/c2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 30, "x"], + ]); + expect(stateVariables["/c2"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 30, "x"], + ]); + expect(stateVariables["/c3"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 30, "x"], + ]); + expect(stateVariables["/c3"].stateValues.valueForDisplay.tree).eqls([ + "apply", + "sin", + ["*", 30, "x"], + ]); + expect(stateVariables["/d"].stateValues.value.tree).eqls([ + "*", + 6.35, + ["^", 10, -14], + ["^", "e", ["*", 0, "y"]], + ]); + expect(stateVariables["/d2"].stateValues.value.tree).eqls([ + "*", + 6.35, + ["^", 10, -14], + ["^", "e", ["*", 0, "y"]], + ]); + expect(stateVariables["/d2"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.35, + ["^", 10, -14], + ["^", "e", ["*", 0, "y"]], + ]); + expect(stateVariables["/d3"].stateValues.value.tree).eqls([ + "*", + 6.35, + ["^", 10, -14], + ["^", "e", ["*", 0, "y"]], + ]); + expect(stateVariables["/d3"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.35, + ["^", 10, -14], + ["^", "e", ["*", 0, "y"]], + ]); + expect(stateVariables["/d4"].stateValues.value.tree).eqls([ + "*", + 6.35, + ["^", 10, -14], + ["^", "e", ["*", 0, "y"]], + ]); + expect(stateVariables["/d4"].stateValues.valueForDisplay.tree).eqls([ + "*", + 6.35, + ["^", 10, -14], + ["^", "e", ["*", 0, "y"]], + ]); + }); + + it("propagate larger default display digits", async () => { + let core = await createTestCore({ + doenetML: ` +

a:

+

a2:

+

a3:

+

a4:

+

a5:

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("123.4567891"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "123.4567891", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "123.4567891", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq( + "123.46", + ); + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq( + "123.46", + ); + + await updateMathInputValue({ + latex: "98765.4321876", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("98765.43219"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "98765.43219", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "98765.43219", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq( + "98765.43", + ); + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq( + "98765.43", + ); + }); + + it("propagate false default display small as zero", async () => { + let core = await createTestCore({ + doenetML: ` +

a:

+

a2:

+

a3:

+

a4:

+

a5:

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("123.4567891"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "123.4567891", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "123.4567891", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq( + "123.4567891", + ); + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq( + "123.4567891", + ); + + await updateMathInputValue({ + latex: "0.00000000000000004736286523434185", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("4.736286523\\cdot10^{-17}"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "4.736286523\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "4.736286523\\cdot10^{-17}", + ); + expect(cleanLatex(stateVariables["/a4"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/a5"].stateValues.latex)).eq("0"); + }); + + it("display digits, change from downstream", async () => { + let core = await createTestCore({ + doenetML: ` +

a:

+ +

b: 5

+

b2:

+ + + ($a, $b2) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eq(3); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eq(3); + expect(stateVariables["/p"].stateValues.xs[0].tree).eq(3); + expect(stateVariables["/b"].stateValues.value.tree).eq(5); + expect(stateVariables["/b"].stateValues.valueForDisplay.tree).eq(5); + expect(stateVariables["/b2"].stateValues.value.tree).eq(5); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eq(5); + expect(stateVariables["/p"].stateValues.xs[1].tree).eq(5); + + await updateMathInputValue({ + latex: "2.4295639461593", + componentName: "/a", + core, + }); + await updateMathInputValue({ + latex: "9.3935596792746", + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eq(2.4295639461593); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eq( + 2.4296, + ); + expect(stateVariables["/p"].stateValues.xs[0].tree).eq(2.4295639461593); + expect(stateVariables["/b"].stateValues.value.tree).eq(9.3935596792746); + expect(stateVariables["/b"].stateValues.valueForDisplay.tree).eq( + 9.393559679, + ); + expect(stateVariables["/b2"].stateValues.value.tree).eq( + 9.3935596792746, + ); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eq(9.39); + expect(stateVariables["/p"].stateValues.xs[1].tree).eq(9.3935596792746); + + await core.requestAction({ + componentName: "/p", + actionName: "movePoint", + args: { x: 7.936497798143, y: 2.142218345836 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eq(7.936497798143); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eq( + 7.9365, + ); + expect(stateVariables["/p"].stateValues.xs[0].tree).eq(7.936497798143); + expect(stateVariables["/b"].stateValues.value.tree).eq(2.142218345836); + expect(stateVariables["/b"].stateValues.valueForDisplay.tree).eq( + 2.142218346, + ); + expect(stateVariables["/b2"].stateValues.value.tree).eq(2.142218345836); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eq(2.14); + expect(stateVariables["/p"].stateValues.xs[1].tree).eq(2.142218345836); + }); + + it("display decimals, change from downstream", async () => { + let core = await createTestCore({ + doenetML: ` +

a:

+ +

b: 5

+

b2:

+ + + ($a, $b2) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eq(3); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eq(3); + expect(stateVariables["/p"].stateValues.xs[0].tree).eq(3); + expect(stateVariables["/b"].stateValues.value.tree).eq(5); + expect(stateVariables["/b"].stateValues.valueForDisplay.tree).eq(5); + expect(stateVariables["/b2"].stateValues.value.tree).eq(5); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eq(5); + expect(stateVariables["/p"].stateValues.xs[1].tree).eq(5); + + await updateMathInputValue({ + latex: "2.4295639461593", + componentName: "/a", + core, + }); + await updateMathInputValue({ + latex: "9.3935596792746", + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eq(2.4295639461593); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eq( + 2.4296, + ); + expect(stateVariables["/p"].stateValues.xs[0].tree).eq(2.4295639461593); + expect(stateVariables["/b"].stateValues.value.tree).eq(9.3935596792746); + expect(stateVariables["/b"].stateValues.valueForDisplay.tree).eq( + 9.393559679, + ); + expect(stateVariables["/b2"].stateValues.value.tree).eq( + 9.3935596792746, + ); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eq(9.39); + expect(stateVariables["/p"].stateValues.xs[1].tree).eq(9.3935596792746); + + await core.requestAction({ + componentName: "/p", + actionName: "movePoint", + args: { x: 7.936497798143, y: 2.142218345836 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eq(7.936497798143); + expect(stateVariables["/a"].stateValues.valueForDisplay.tree).eq( + 7.9365, + ); + expect(stateVariables["/p"].stateValues.xs[0].tree).eq(7.936497798143); + expect(stateVariables["/b"].stateValues.value.tree).eq(2.142218345836); + expect(stateVariables["/b"].stateValues.valueForDisplay.tree).eq( + 2.142218346, + ); + expect(stateVariables["/b2"].stateValues.value.tree).eq(2.142218345836); + expect(stateVariables["/b2"].stateValues.valueForDisplay.tree).eq(2.14); + expect(stateVariables["/p"].stateValues.xs[1].tree).eq(2.142218345836); + }); + + it("substitute unicode", async () => { + let core = await createTestCore({ + doenetML: ` +

a:

+

a2: $a.value{assignNames="a2"}

+

a3:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a2"].stateValues.value.tree).eq("\uff3f"); + + // unicode Ξ± U+03B1 + await updateMathInputValue({ + latex: "Ξ±", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("Ξ±"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\alpha", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\alpha", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls("alpha"); + expect(stateVariables["/a2"].stateValues.value.tree).eqls("alpha"); + expect(stateVariables["/a3"].stateValues.value.tree).eqls("alpha"); + + // latex \\alpha\\beta + await updateMathInputValue({ + latex: "\\alpha\\beta", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\\alpha\\beta"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\alpha\\beta", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\alpha\\beta", + ); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + "alpha", + "beta", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + "alpha", + "beta", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + "alpha", + "beta", + ]); + + // unicode βˆ’ U+2212 is subtraction + + await updateMathInputValue({ + latex: "y\u2212z", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("y\u2212z"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("y-z"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("y-z"); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "+", + "y", + ["-", "z"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "+", + "y", + ["-", "z"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "+", + "y", + ["-", "z"], + ]); + + // normal minus + + await updateMathInputValue({ + latex: "a-b", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("a-b"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("a-b"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("a-b"); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "+", + "a", + ["-", "b"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "+", + "a", + ["-", "b"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "+", + "a", + ["-", "b"], + ]); + + // unicode β‹… U+22C5 is multiplication + + await updateMathInputValue({ + latex: "y\u22C5z", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("y\u22C5z"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("yz"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("yz"); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + "y", + "z", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + "y", + "z", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + "y", + "z", + ]); + + // normal * + + await updateMathInputValue({ + latex: "a*b", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("a*b"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("ab"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("ab"); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + ]); + + // unicode Β· U+00B7 becomes multiplication + + await updateMathInputValue({ + latex: "y\u00B7z", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("y\u00B7z"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("yz"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("yz"); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + "y", + "z", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + "y", + "z", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + "y", + "z", + ]); + + // unicode Γ— U+00D7 becomes multiplication + + await updateMathInputValue({ + latex: "u\u00D7v", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("u\u00D7v"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("uv"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("uv"); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + "u", + "v", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + "u", + "v", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + "u", + "v", + ]); + + // unicode βˆͺ U+222A becomes union + + await updateMathInputValue({ + latex: "A\u222AB", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("A\u222AB"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "A\\cupB", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "A\\cupB", + ); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + + // unicode ∩ U+2229 becomes intersect + + await updateMathInputValue({ + latex: "A\u2229B", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("A\u2229B"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "A\\capB", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "A\\capB", + ); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "intersect", + "A", + "B", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "intersect", + "A", + "B", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "intersect", + "A", + "B", + ]); + + // unicode ∞ U+221E becomes infinity + + await updateMathInputValue({ + latex: "\u221E", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\u221E"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq( + "\\infty", + ); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq( + "\\infty", + ); + expect(stateVariables["/a"].stateValues.value.tree).eq(Infinity); + expect(stateVariables["/a2"].stateValues.value.tree).eq(Infinity); + expect(stateVariables["/a3"].stateValues.value.tree).eq(Infinity); + + // unicode Β΅ U+00B5 becomes mu + + await updateMathInputValue({ + latex: "\u00B5", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\u00B5"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("\\mu"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("\\mu"); + expect(stateVariables["/a"].stateValues.value.tree).eq("mu"); + expect(stateVariables["/a2"].stateValues.value.tree).eq("mu"); + expect(stateVariables["/a3"].stateValues.value.tree).eq("mu"); + + // unicode ΞΌ U+03BC becomes mu + + await updateMathInputValue({ + latex: "\u03BC", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("\u03BC"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("\\mu"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("\\mu"); + expect(stateVariables["/a"].stateValues.value.tree).eq("mu"); + expect(stateVariables["/a2"].stateValues.value.tree).eq("mu"); + expect(stateVariables["/a3"].stateValues.value.tree).eq("mu"); + + // unicode β€² U+2032 becomes apostrophe + + await updateMathInputValue({ + latex: "f\u2032", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/a"].stateValues.rawRendererValue), + ).eq("f\u2032"); + expect(cleanLatex(stateVariables["/a2"].stateValues.latex)).eq("f'"); + expect(cleanLatex(stateVariables["/a3"].stateValues.latex)).eq("f'"); + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "prime", + "f", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "prime", + "f", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "prime", + "f", + ]); + }); + + it("exponent with numbers", async () => { + let core = await createTestCore({ + doenetML: ` +

a:

+

a2: $a.value{assignNames="a2"}

+

a3: $a

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/a2"].stateValues.value.tree)).eq( + "\uff3f", + ); + + await updateMathInputValue({ + latex: "3^25", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["^", 3, 2], + 5, + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["^", 3, 2], + 5, + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls(45); + + await updateMathInputValue({ + latex: "3^{25}", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls(["^", 3, 25]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls(["^", 3, 25]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls(847288609443); + + await updateMathInputValue({ + latex: "3^{2x}", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "^", + 3, + ["*", 2, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "^", + 3, + ["*", 2, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "^", + 3, + ["*", 2, "x"], + ]); + + await updateMathInputValue({ + latex: "3^2x", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["^", 3, 2], + "x", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["^", 3, 2], + "x", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + 9, + "x", + ]); + + await updateMathInputValue({ + latex: "3^{x2}", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "^", + 3, + "x2", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "^", + 3, + "x2", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "^", + 3, + "x2", + ]); + + await updateMathInputValue({ + latex: "3^x2", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["^", 3, "x"], + 2, + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["^", 3, "x"], + 2, + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + 2, + ["^", 3, "x"], + ]); + + await updateMathInputValue({ + latex: "f^32", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["^", "f", 3], + 2, + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["^", "f", 3], + 2, + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + 2, + ["^", "f", 3], + ]); + + await updateMathInputValue({ + latex: "x^32", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["^", "x", 3], + 2, + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["^", "x", 3], + 2, + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + 2, + ["^", "x", 3], + ]); + }); + + it("subscript with numbers", async () => { + let core = await createTestCore({ + doenetML: ` +

a:

+

a2: $a.value{assignNames="a2"}

+

a3: $a

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a2"].stateValues.value.tree).eqls("\uff3f"); + + await updateMathInputValue({ + latex: "3_25", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["_", 3, 2], + 5, + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["_", 3, 2], + 5, + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + 5, + ["_", 3, 2], + ]); + + await updateMathInputValue({ + latex: "3_{25}", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls(["_", 3, 25]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls(["_", 3, 25]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls(["_", 3, 25]); + + await updateMathInputValue({ + latex: "3_{2x}", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "_", + 3, + ["*", 2, "x"], + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "_", + 3, + ["*", 2, "x"], + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "_", + 3, + ["*", 2, "x"], + ]); + + await updateMathInputValue({ + latex: "3_2x", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["_", 3, 2], + "x", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["_", 3, 2], + "x", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + "x", + ["_", 3, 2], + ]); + + await updateMathInputValue({ + latex: "3_{x2}", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "_", + 3, + "x2", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "_", + 3, + "x2", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "_", + 3, + "x2", + ]); + + await updateMathInputValue({ + latex: "3_x2", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["_", 3, "x"], + 2, + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["_", 3, "x"], + 2, + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", 3, "x"], + ]); + + await updateMathInputValue({ + latex: "f_32", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["_", "f", 3], + 2, + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["_", "f", 3], + 2, + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "f", 3], + ]); + + await updateMathInputValue({ + latex: "x_32", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value.tree).eqls([ + "*", + ["_", "x", 3], + 2, + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "*", + ["_", "x", 3], + 2, + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "*", + 2, + ["_", "x", 3], + ]); + }); + + it("rawValue is updated", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("1"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi"].stateValues.value.tree).eq(1); + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 3, + ]); + + await updateMathInputValue({ + latex: "-7.4", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("-7"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eq(-7); + expect(stateVariables["/mi"].stateValues.value.tree).eq(-7); + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls([ + -7, 2, + ]); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls([ + -7, 3, + ]); + + // move point A + + await core.requestAction({ + componentName: "/A", + actionName: "movePoint", + args: { x: 3.9, y: -8.4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("4"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eq(4); + expect(stateVariables["/mi"].stateValues.value.tree).eq(4); + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls([ + 4, -8, + ]); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls([ + 4, 3, + ]); + + // move point B + + await core.requestAction({ + componentName: "/B", + actionName: "movePoint", + args: { x: 5.1, y: 1.3 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("5"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eq(5); + expect(stateVariables["/mi"].stateValues.value.tree).eq(5); + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls([ + 5, -8, + ]); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls([ + 5, 1.3, + ]); + }); + + it("chain update off mathinput", async () => { + let core = await createTestCore({ + doenetML: ` + + + x + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/x"].stateValues.value.tree).eq("x"); + + await updateMathInputImmediateValue({ + latex: "y", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eq("y"); + expect(stateVariables["/x"].stateValues.value.tree).eq("x"); + + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi", + core, + }); + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eq("x"); + expect(stateVariables["/x"].stateValues.value.tree).eq("x"); + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eq("x"); + expect(stateVariables["/x"].stateValues.value.tree).eqls(["*", 2, "x"]); + + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi", + core, + }); + await updateMathInputImmediateValue({ + latex: "y", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eq("y"); + expect(stateVariables["/x"].stateValues.value.tree).eqls(["*", 2, "x"]); + + await updateMathInputImmediateValue({ + latex: "y+x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "+", + "y", + "x", + ]); + expect(stateVariables["/x"].stateValues.value.tree).eqls(["*", 2, "x"]); + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "+", + "y", + "x", + ]); + expect(stateVariables["/x"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + "y", + ]); + }); + + it("split symbols in mathinput", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

No split:

+

Split:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mns"].stateValues.value.tree).eq("\uff3f"); + + await updateMathInputValue({ + latex: "xy", + componentName: "/mins", + core, + }); + await updateMathInputValue({ + latex: "xy", + componentName: "/mis", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mins"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/mis"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/mns"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/ms"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + + await updateMathInputValue({ + latex: "xy0", + componentName: "/mins", + core, + }); + await updateMathInputValue({ + latex: "xy0", + componentName: "/mis", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mins"].stateValues.value.tree).eqls("xy0"); + expect(stateVariables["/mis"].stateValues.value.tree).eqls("xy0"); + expect(stateVariables["/mns"].stateValues.value.tree).eqls("xy0"); + expect(stateVariables["/ms"].stateValues.value.tree).eqls("xy0"); + + await updateMathInputValue({ + latex: "xy_{uv}", + componentName: "/mins", + core, + }); + await updateMathInputValue({ + latex: "xy_{uv}", + componentName: "/mis", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mins"].stateValues.value.tree).eqls([ + "_", + "xy", + "uv", + ]); + expect(stateVariables["/mis"].stateValues.value.tree).eqls([ + "*", + "x", + ["_", "y", ["*", "u", "v"]], + ]); + expect(stateVariables["/mns"].stateValues.value.tree).eqls([ + "_", + "xy", + "uv", + ]); + expect(stateVariables["/ms"].stateValues.value.tree).eqls([ + "*", + "x", + ["_", "y", ["*", "u", "v"]], + ]); + }); + + it("normalize begin/end ldots in mathinput", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Value:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m"].stateValues.value.tree).eq("\uff3f"); + + // use periods, no commas + + await updateMathInputValue({ + latex: "...x,y,z...", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "x", + "y", + "z", + ["ldots"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "x", + "y", + "z", + ["ldots"], + ]); + + // add spaces in between some periods + + await updateMathInputValue({ + latex: "\\ .\\ .\\ .x,y,a..\\ .\\ ", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "x", + "y", + "a", + ["ldots"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "x", + "y", + "a", + ["ldots"], + ]); + + // add commas after first set of periods + + await updateMathInputValue({ + latex: "\\ .\\ .\\ .,b,y,a..\\ .\\ ", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "b", + "y", + "a", + ["ldots"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "b", + "y", + "a", + ["ldots"], + ]); + + // add commas before second set of periods + + await updateMathInputValue({ + latex: "\\ .\\ .\\ .,b,y,c,..\\ .\\ ", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "b", + "y", + "c", + ["ldots"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "b", + "y", + "c", + ["ldots"], + ]); + + // change second set of periods to ldots + + await updateMathInputValue({ + latex: "\\ .\\ .\\ .,b,y,d,\\ldots\\ ", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "b", + "y", + "d", + ["ldots"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "b", + "y", + "d", + ["ldots"], + ]); + + // change first set of periods to ldots + + await updateMathInputValue({ + latex: "\\ \\ldots\\ ,e,y,d,\\ldots\\ ", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "e", + "y", + "d", + ["ldots"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "e", + "y", + "d", + ["ldots"], + ]); + + // remove first comma + + await updateMathInputValue({ + latex: "\\ \\ldots\\ f,y,d,\\ldots\\ ", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "f", + "y", + "d", + ["ldots"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "f", + "y", + "d", + ["ldots"], + ]); + + // remove last comma + + await updateMathInputValue({ + latex: "\\ \\ldots\\ f,y,g\\ldots\\ ", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "f", + "y", + "g", + ["ldots"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "list", + ["ldots"], + "f", + "y", + "g", + ["ldots"], + ]); + }); + + it("mathinput eliminates multicharacter symbols", async () => { + let core = await createTestCore({ + doenetML: ` + x2 + xyz + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/varWithNum"].stateValues.value.tree).eq("x2"); + expect(stateVariables["/varWithNum2"].stateValues.value.tree).eq("x2"); + expect(stateVariables["/varWithNum3"].stateValues.value.tree).eq("x2"); + expect(stateVariables["/noSplit"].stateValues.value.tree).eq("xyz"); + expect(stateVariables["/noSplit2"].stateValues.value.tree).eq("xyz"); + expect(stateVariables["/noSplit3"].stateValues.value.tree).eq("xyz"); + + await updateMathInputValue({ + latex: "xu9j", + componentName: "/varWithNum2", + core, + }); + await updateMathInputValue({ + latex: "xyuv", + componentName: "/noSplit2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/varWithNum"].stateValues.value.tree).eq("xu9j"); + expect(stateVariables["/varWithNum2"].stateValues.value.tree).eq( + "xu9j", + ); + expect(stateVariables["/varWithNum3"].stateValues.value.tree).eq( + "xu9j", + ); + expect(stateVariables["/noSplit"].stateValues.value.tree).eq("xyuv"); + expect(stateVariables["/noSplit2"].stateValues.value.tree).eq("xyuv"); + expect(stateVariables["/noSplit3"].stateValues.value.tree).eq("xyuv"); + }); + + it("mathinput prefills 1", async () => { + let core = await createTestCore({ + doenetML: ` +

+ A \\cup B + A union B + A \\cup B +

+ +

+ + + + + + + + $union1.value{assignNames="union1m"} + $union2.value{assignNames="union2m"} + $union3.value{assignNames="union3m"} + $union4.value{assignNames="union4m"} + $union5.value{assignNames="union5m"} + $union6.value{assignNames="union6m"} + $union7.value{assignNames="union7m"} +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/union1"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union2"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union3"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union4"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union5"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union6"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union7"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union1m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union2m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union3m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union4m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union5m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union6m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/union7m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + }); + + it("mathinput prefills 2", async () => { + let core = await createTestCore({ + doenetML: ` +

+ xy + xy +

+ + +

+ + + + + + + + + $splits1.value{assignNames="splits1m"} + $splits2.value{assignNames="splits2m"} + $splits3.value{assignNames="splits3m"} + $splits4.value{assignNames="splits4m"} + $splits5.value{assignNames="splits5m"} + $splits6.value{assignNames="splits6m"} + $splits7.value{assignNames="splits7m"} + $splits8.value{assignNames="splits8m"} +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/splits1"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/splits2"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/splits3"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/splits4"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/splits5"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/splits6"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/splits7"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/splits8"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/splits1m"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/splits2m"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/splits3m"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/splits4m"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/splits5m"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/splits6m"].stateValues.value.tree).eqls("xy"); + expect(stateVariables["/splits7m"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/splits8m"].stateValues.value.tree).eqls("xy"); + + await updateMathInputValue({ + latex: "xyz", + componentName: "/splits1", + core, + }); + await updateMathInputValue({ + latex: "xyz", + componentName: "/splits2", + core, + }); + await updateMathInputValue({ + latex: "xyz", + componentName: "/splits3", + core, + }); + await updateMathInputValue({ + latex: "xyz", + componentName: "/splits4", + core, + }); + await updateMathInputValue({ + latex: "xyz", + componentName: "/splits5", + core, + }); + await updateMathInputValue({ + latex: "xyz", + componentName: "/splits6", + core, + }); + await updateMathInputValue({ + latex: "xyz", + componentName: "/splits7", + core, + }); + await updateMathInputValue({ + latex: "xyz", + componentName: "/splits8", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/splits1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/splits2"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/splits3"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/splits4"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/splits5"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/splits6"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/splits7"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/splits8"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/splits1m"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/splits2m"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/splits3m"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/splits4m"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/splits5m"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/splits6m"].stateValues.value.tree).eqls("xyz"); + expect(stateVariables["/splits7m"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + "z", + ]); + expect(stateVariables["/splits8m"].stateValues.value.tree).eqls("xyz"); + }); + + it("mathinput prefills 3", async () => { + let core = await createTestCore({ + doenetML: ` +

+ h(x) + h(x) +

+ +

+ + + + + + + + + $hFunction1.value{assignNames="hFunction1m"} + $hFunction2.value{assignNames="hFunction2m"} + $hFunction3.value{assignNames="hFunction3m"} + $hFunction4.value{assignNames="hFunction4m"} + $hFunction5.value{assignNames="hFunction5m"} + $hFunction6.value{assignNames="hFunction6m"} + $hFunction7.value{assignNames="hFunction7m"} + $hFunction8.value{assignNames="hFunction8m"} +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/hFunction1"].stateValues.rawRendererValue, + ), + ).eq("h(x)"); + expect( + cleanLatex( + stateVariables["/hFunction2"].stateValues.rawRendererValue, + ), + ).eq("h(x)"); + expect( + cleanLatex( + stateVariables["/hFunction3"].stateValues.rawRendererValue, + ), + ).eq("hx"); + expect( + cleanLatex( + stateVariables["/hFunction4"].stateValues.rawRendererValue, + ), + ).eq("hx"); + expect( + cleanLatex( + stateVariables["/hFunction5"].stateValues.rawRendererValue, + ), + ).eq("hx"); + expect( + cleanLatex( + stateVariables["/hFunction6"].stateValues.rawRendererValue, + ), + ).eq("h(x)"); + expect( + cleanLatex( + stateVariables["/hFunction7"].stateValues.rawRendererValue, + ), + ).eq("h(x)"); + expect( + cleanLatex( + stateVariables["/hFunction8"].stateValues.rawRendererValue, + ), + ).eq("h(x)"); + + expect(cleanLatex(stateVariables["/hFunction1m"].stateValues.latex)).eq( + "h(x)", + ); + expect(cleanLatex(stateVariables["/hFunction2m"].stateValues.latex)).eq( + "h(x)", + ); + expect(cleanLatex(stateVariables["/hFunction3m"].stateValues.latex)).eq( + "hx", + ); + expect(cleanLatex(stateVariables["/hFunction4m"].stateValues.latex)).eq( + "hx", + ); + expect(cleanLatex(stateVariables["/hFunction5m"].stateValues.latex)).eq( + "hx", + ); + expect(cleanLatex(stateVariables["/hFunction6m"].stateValues.latex)).eq( + "h(x)", + ); + expect(cleanLatex(stateVariables["/hFunction7m"].stateValues.latex)).eq( + "hx", + ); + expect(cleanLatex(stateVariables["/hFunction8m"].stateValues.latex)).eq( + "h(x)", + ); + + expect(stateVariables["/hFunction1"].stateValues.value.tree).eqls([ + "apply", + "h", + "x", + ]); + expect(stateVariables["/hFunction2"].stateValues.value.tree).eqls([ + "apply", + "h", + "x", + ]); + expect(stateVariables["/hFunction3"].stateValues.value.tree).eqls([ + "*", + "h", + "x", + ]); + expect(stateVariables["/hFunction4"].stateValues.value.tree).eqls([ + "*", + "h", + "x", + ]); + expect(stateVariables["/hFunction5"].stateValues.value.tree).eqls([ + "*", + "h", + "x", + ]); + expect(stateVariables["/hFunction6"].stateValues.value.tree).eqls([ + "apply", + "h", + "x", + ]); + expect(stateVariables["/hFunction7"].stateValues.value.tree).eqls([ + "*", + "h", + "x", + ]); + expect(stateVariables["/hFunction8"].stateValues.value.tree).eqls([ + "apply", + "h", + "x", + ]); + expect(stateVariables["/hFunction1m"].stateValues.value.tree).eqls([ + "apply", + "h", + "x", + ]); + expect(stateVariables["/hFunction2m"].stateValues.value.tree).eqls([ + "apply", + "h", + "x", + ]); + expect(stateVariables["/hFunction3m"].stateValues.value.tree).eqls([ + "*", + "h", + "x", + ]); + expect(stateVariables["/hFunction4m"].stateValues.value.tree).eqls([ + "*", + "h", + "x", + ]); + expect(stateVariables["/hFunction5m"].stateValues.value.tree).eqls([ + "*", + "h", + "x", + ]); + expect(stateVariables["/hFunction6m"].stateValues.value.tree).eqls([ + "apply", + "h", + "x", + ]); + expect(stateVariables["/hFunction7m"].stateValues.value.tree).eqls([ + "*", + "h", + "x", + ]); + expect(stateVariables["/hFunction8m"].stateValues.value.tree).eqls([ + "apply", + "h", + "x", + ]); + + await updateMathInputValue({ + latex: "h(y)", + componentName: "/hFunction1", + core, + }); + await updateMathInputValue({ + latex: "h(y)", + componentName: "/hFunction2", + core, + }); + await updateMathInputValue({ + latex: "h(y)", + componentName: "/hFunction3", + core, + }); + await updateMathInputValue({ + latex: "h(y)", + componentName: "/hFunction4", + core, + }); + await updateMathInputValue({ + latex: "h(y)", + componentName: "/hFunction5", + core, + }); + await updateMathInputValue({ + latex: "h(y)", + componentName: "/hFunction6", + core, + }); + await updateMathInputValue({ + latex: "h(y)", + componentName: "/hFunction7", + core, + }); + await updateMathInputValue({ + latex: "h(y)", + componentName: "/hFunction8", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/hFunction1"].stateValues.rawRendererValue, + ), + ).eq("h(y)"); + expect( + cleanLatex( + stateVariables["/hFunction2"].stateValues.rawRendererValue, + ), + ).eq("h(y)"); + expect( + cleanLatex( + stateVariables["/hFunction3"].stateValues.rawRendererValue, + ), + ).eq("h(y)"); + expect( + cleanLatex( + stateVariables["/hFunction4"].stateValues.rawRendererValue, + ), + ).eq("h(y)"); + expect( + cleanLatex( + stateVariables["/hFunction5"].stateValues.rawRendererValue, + ), + ).eq("h(y)"); + expect( + cleanLatex( + stateVariables["/hFunction6"].stateValues.rawRendererValue, + ), + ).eq("h(y)"); + expect( + cleanLatex( + stateVariables["/hFunction7"].stateValues.rawRendererValue, + ), + ).eq("h(y)"); + expect( + cleanLatex( + stateVariables["/hFunction8"].stateValues.rawRendererValue, + ), + ).eq("h(y)"); + + expect(cleanLatex(stateVariables["/hFunction1m"].stateValues.latex)).eq( + "hy", + ); + expect(cleanLatex(stateVariables["/hFunction2m"].stateValues.latex)).eq( + "h(y)", + ); + expect(cleanLatex(stateVariables["/hFunction3m"].stateValues.latex)).eq( + "hy", + ); + expect(cleanLatex(stateVariables["/hFunction4m"].stateValues.latex)).eq( + "h(y)", + ); + expect(cleanLatex(stateVariables["/hFunction5m"].stateValues.latex)).eq( + "hy", + ); + expect(cleanLatex(stateVariables["/hFunction6m"].stateValues.latex)).eq( + "h(y)", + ); + expect(cleanLatex(stateVariables["/hFunction7m"].stateValues.latex)).eq( + "hy", + ); + expect(cleanLatex(stateVariables["/hFunction8m"].stateValues.latex)).eq( + "h(y)", + ); + + expect(stateVariables["/hFunction1"].stateValues.value.tree).eqls([ + "*", + "h", + "y", + ]); + expect(stateVariables["/hFunction2"].stateValues.value.tree).eqls([ + "apply", + "h", + "y", + ]); + expect(stateVariables["/hFunction3"].stateValues.value.tree).eqls([ + "*", + "h", + "y", + ]); + expect(stateVariables["/hFunction4"].stateValues.value.tree).eqls([ + "apply", + "h", + "y", + ]); + expect(stateVariables["/hFunction5"].stateValues.value.tree).eqls([ + "*", + "h", + "y", + ]); + expect(stateVariables["/hFunction6"].stateValues.value.tree).eqls([ + "apply", + "h", + "y", + ]); + expect(stateVariables["/hFunction7"].stateValues.value.tree).eqls([ + "*", + "h", + "y", + ]); + expect(stateVariables["/hFunction8"].stateValues.value.tree).eqls([ + "apply", + "h", + "y", + ]); + expect(stateVariables["/hFunction1m"].stateValues.value.tree).eqls([ + "*", + "h", + "y", + ]); + expect(stateVariables["/hFunction2m"].stateValues.value.tree).eqls([ + "apply", + "h", + "y", + ]); + expect(stateVariables["/hFunction3m"].stateValues.value.tree).eqls([ + "*", + "h", + "y", + ]); + expect(stateVariables["/hFunction4m"].stateValues.value.tree).eqls([ + "apply", + "h", + "y", + ]); + expect(stateVariables["/hFunction5m"].stateValues.value.tree).eqls([ + "*", + "h", + "y", + ]); + expect(stateVariables["/hFunction6m"].stateValues.value.tree).eqls([ + "apply", + "h", + "y", + ]); + expect(stateVariables["/hFunction7m"].stateValues.value.tree).eqls([ + "*", + "h", + "y", + ]); + expect(stateVariables["/hFunction8m"].stateValues.value.tree).eqls([ + "apply", + "h", + "y", + ]); + }); + + it("prefillFromLatex", async () => { + let core = await createTestCore({ + doenetML: ` +

Prefill with m: \\frac{a}{b} \\int_a^b \\hat{f}(x) dx

+

Result:

+

Value: $input1{name="iv1"}

+

Raw value: $input1.rawRendererValue

+ +

Prefill with phrase including "\\ "

+

Result:

+

Value: $input2{name="iv2"}

+

Raw value: $input2.rawRendererValue

+ +

Prefill with a \\text

+

Result:

+

Value: $input3{name="iv3"}

+

Raw value: $input3.rawRendererValue

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/input1"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/input1"].stateValues.immediateValue.tree).eq( + "\uff3f", + ); + expect(stateVariables["/input1"].stateValues.rawRendererValue).eq( + "\\frac{a}{b} \\int_a^b \\hat{f}(x) dx", + ); + expect(stateVariables["/input2"].stateValues.value.tree).eqls([ + "*", + "h", + "e", + "l", + "l", + "o", + "t", + "h", + "e", + "r", + "e", + "a", + "b", + ]); + expect(stateVariables["/input2"].stateValues.immediateValue.tree).eqls([ + "*", + "h", + "e", + "l", + "l", + "o", + "t", + "h", + "e", + "r", + "e", + "a", + "b", + ]); + expect(stateVariables["/input2"].stateValues.rawRendererValue).eq( + "hello\\ there (a)(b)", + ); + expect(stateVariables["/input3"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/input3"].stateValues.immediateValue.tree).eq( + "\uff3f", + ); + expect(stateVariables["/input3"].stateValues.rawRendererValue).eq( + "\\text{hello there} (a)(b)", + ); + + await updateMathInputValue({ + latex: "\\frac{a}{b} \\int_a^b f(x) dx", + componentName: "/input1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/iv1"].stateValues.latex)).eq( + "(\\frac{a}{b})\\int_{a}^{b}f(x)dx", + ); + expect(stateVariables["/pr1"].stateValues.text).eq( + "Raw value: \\frac{a}{b} \\int_a^b f(x) dx", + ); + + // expect(stateVariables['/input1'].stateValues.value.tree).eqls(["*", ["/", "a", "b"], "a", ["apply", "f", "x"], "d", "x"]) + // expect(stateVariables['/input1'].stateValues.immediateValue.tree).eqls(["*", ["/", "a", "b"], "a", ["apply", "f", "x"], "d", "x"]) + expect( + cleanLatex(stateVariables["/input1"].stateValues.rawRendererValue), + ).eq("\\frac{a}{b}\\int_a^bf(x)dx"); + + await updateMathInputValue({ + latex: "hello(a)(b)", + componentName: "/input2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/iv2"].stateValues.latex)).eq( + "helloab", + ); + expect(stateVariables["/pr2"].stateValues.text).eq( + "Raw value: hello(a)(b)", + ); + + expect(stateVariables["/input2"].stateValues.value.tree).eqls([ + "*", + "h", + "e", + "l", + "l", + "o", + "a", + "b", + ]); + expect(stateVariables["/input2"].stateValues.immediateValue.tree).eqls([ + "*", + "h", + "e", + "l", + "l", + "o", + "a", + "b", + ]); + expect(stateVariables["/input2"].stateValues.rawRendererValue).eq( + "hello(a)(b)", + ); + + await updateMathInputValue({ + latex: "\\text{h}(a)(b)", + componentName: "/input3", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/iv3"].stateValues.latex)).eq( + "\uff3f", + ); + expect(stateVariables["/pr3"].stateValues.text).eq( + "Raw value: \\text{h}(a)(b)", + ); + + expect(stateVariables["/input3"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/input3"].stateValues.immediateValue.tree).eq( + "\uff3f", + ); + expect(stateVariables["/input3"].stateValues.rawRendererValue).eq( + "\\text{h}(a)(b)", + ); + + await updateMathInputValue({ + latex: "(a)(b)", + componentName: "/input3", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/iv3"].stateValues.latex)).eq("ab"); + expect(stateVariables["/pr3"].stateValues.text).eq("Raw value: (a)(b)"); + + expect(stateVariables["/input3"].stateValues.value.tree).eqls([ + "*", + "a", + "b", + ]); + expect(stateVariables["/input3"].stateValues.immediateValue.tree).eqls([ + "*", + "a", + "b", + ]); + expect(stateVariables["/input3"].stateValues.rawRendererValue).eq( + "(a)(b)", + ); + }); + + it("convert and/or into logicals", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Value:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m"].stateValues.value.tree).eq("\uff3f"); + + // equalities with or + + await updateMathInputValue({ + latex: "x=1 or u=x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "or", + ["=", "x", 1], + ["=", "u", "x"], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "or", + ["=", "x", 1], + ["=", "u", "x"], + ]); + + // inequalities with and + await updateMathInputValue({ + latex: "x>3 and x \\le 5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "and", + [">", "x", 3], + ["le", "x", 5], + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "and", + [">", "x", 3], + ["le", "x", 5], + ]); + + // don't convert if not word + await updateMathInputValue({ + latex: "AandBorC", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "*", + "A", + "a", + "n", + "d", + "B", + "o", + "r", + "C", + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "*", + "A", + "a", + "n", + "d", + "B", + "o", + "r", + "C", + ]); + + // add parens or spaces + await updateMathInputValue({ + latex: "(A)and B or(C)", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "or", + ["and", "A", "B"], + "C", + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "or", + ["and", "A", "B"], + "C", + ]); + }); + + it("union from U", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

Value:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m"].stateValues.value.tree).eq("\uff3f"); + + // A U C without unionFromU + + await updateMathInputValue({ + latex: "A U C", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "*", + "A", + "U", + "C", + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "*", + "A", + "U", + "C", + ]); + + // activate unionFromU and modify text + + await updateBooleanInputValue({ + boolean: true, + componentName: "/ufu", + core, + }); + await updateMathInputValue({ + latex: "A U B", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + + // no substitution without spaces + + await updateMathInputValue({ + latex: "A UB", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "*", + "A", + "U", + "B", + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "*", + "A", + "U", + "B", + ]); + + // add parens + + await updateMathInputValue({ + latex: "A U(B)", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "union", + "A", + "B", + ]); + }); + + it("mathinput can merge coordinates", async () => { + let core = await createTestCore({ + doenetML: ` + + + + +

Change x-coordinate:

+

Change y-coordinate:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/coords"].stateValues.rawRendererValue), + ).eq("(1,2)"); + + await updateMathInputValue({ + latex: "3", + componentName: "/x1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/coords"].stateValues.rawRendererValue), + ).eq("(3,2)"); + + await updateMathInputValue({ + latex: "4", + componentName: "/x2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/coords"].stateValues.rawRendererValue), + ).eq("(3,4)"); + }); + + it("mathinput can merge coordinates, immediateValue", async () => { + let core = await createTestCore({ + doenetML: ` + + + + +

Change x-coordinate:

+

Change y-coordinate:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/coords"].stateValues.rawRendererValue), + ).eq("(1,2)"); + + await updateMathInputValue({ + latex: "3", + componentName: "/x1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/coords"].stateValues.rawRendererValue), + ).eq("(3,2)"); + + await updateMathInputValue({ + latex: "4", + componentName: "/x2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/coords"].stateValues.rawRendererValue), + ).eq("(3,4)"); + }); + + it("change prefill", async () => { + let core = await createTestCore({ + doenetML: ` +

+

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

+

Prefill:

+

Change prefill:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pf"].stateValues.value.tree).eqls([ + "tuple", + 1, + 2, + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "tuple", + 1, + 2, + ]); + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "tuple", + 1, + 2, + ]); + expect(stateVariables["/mi"].stateValues.prefill.tree).eqls([ + "tuple", + 1, + 2, + ]); + expect(stateVariables["/mipf"].stateValues.value.tree).eqls([ + "tuple", + 1, + 2, + ]); + + // change prefill + + await updateMathInputValue({ + latex: "(1,5)", + componentName: "/mipf", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pf"].stateValues.value.tree).eqls([ + "tuple", + 1, + 5, + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "tuple", + 1, + 5, + ]); + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "tuple", + 1, + 5, + ]); + expect(stateVariables["/mi"].stateValues.prefill.tree).eqls([ + "tuple", + 1, + 5, + ]); + expect(stateVariables["/mipf"].stateValues.value.tree).eqls([ + "tuple", + 1, + 5, + ]); + + // change value + + await updateMathInputValue({ + latex: "(1,9)", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pf"].stateValues.value.tree).eqls([ + "tuple", + 1, + 5, + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "tuple", + 1, + 9, + ]); + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "tuple", + 1, + 9, + ]); + expect(stateVariables["/mi"].stateValues.prefill.tree).eqls([ + "tuple", + 1, + 5, + ]); + expect(stateVariables["/mipf"].stateValues.value.tree).eqls([ + "tuple", + 1, + 5, + ]); + + // change prefill again + + await updateMathInputValue({ + latex: "(1,7)", + componentName: "/mipf", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pf"].stateValues.value.tree).eqls([ + "tuple", + 1, + 7, + ]); + expect(stateVariables["/m"].stateValues.value.tree).eqls([ + "tuple", + 1, + 9, + ]); + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "tuple", + 1, + 9, + ]); + expect(stateVariables["/mi"].stateValues.prefill.tree).eqls([ + "tuple", + 1, + 7, + ]); + expect(stateVariables["/mipf"].stateValues.value.tree).eqls([ + "tuple", + 1, + 7, + ]); + }); + + it("mathinput with number child", async () => { + let core = await createTestCore({ + doenetML: ` +

+

Value: $mi.value{assignNames="mv"}

+

Immediate Value: $mi.immediateValue{assignNames="miv"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls(""); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(NaN); + + // type a number + + await updateMathInputImmediateValue({ + latex: "5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("5"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(5); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("5"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(5); + + // type pi + + await updateMathInputImmediateValue({ + latex: "\\pi", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/miv"].stateValues.value.tree).eqls("pi"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("\\pi"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + "pi", + ); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/miv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "3.141592654", + ); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + Math.PI, + ); + + // type x + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("x"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls("x"); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls(""); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(NaN); + + // type 2/3 + + await updateMathInputImmediateValue({ + latex: "2/3", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(["/", 2, 3]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("2/3"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "/", + 2, + 3, + ]); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 0.6666666667, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/miv"].stateValues.valueForDisplay.tree).eqls( + 0.6666666667, + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "0.6666666667", + ); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + 2 / 3, + ); + }); + + it("mathinput with number child, do not hide NaN", async () => { + let core = await createTestCore({ + doenetML: ` +

+

Value: $mi.value{assignNames="mv"}

+

Immediate Value: $mi.immediateValue{assignNames="miv"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("NaN"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(NaN); + + // type a number + + await updateMathInputImmediateValue({ + latex: "5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("5"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(5); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("5"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(5); + + // type pi + + await updateMathInputImmediateValue({ + latex: "\\pi", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/miv"].stateValues.value.tree).eqls("pi"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("\\pi"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + "pi", + ); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/miv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "3.141592654", + ); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + Math.PI, + ); + + // type x + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("x"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls("x"); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("NaN"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(NaN); + + // type 2/3 + + await updateMathInputImmediateValue({ + latex: "2/3", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(["/", 2, 3]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("2/3"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "/", + 2, + 3, + ]); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 0.6666666667, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/miv"].stateValues.valueForDisplay.tree).eqls( + 0.6666666667, + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "0.6666666667", + ); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + 2 / 3, + ); + }); + + it("mathinput with number child, value on NaN", async () => { + let core = await createTestCore({ + doenetML: ` +

+

Value: $mi.value{assignNames="mv"}

+

Immediate Value: $mi.immediateValue{assignNames="miv"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mv"].stateValues.value.tree).eqls(0); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(0); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("0"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(0); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(0); + + // type a number + + await updateMathInputImmediateValue({ + latex: "5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(0); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("5"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(0); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(5); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("5"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(5); + + // type pi + + await updateMathInputImmediateValue({ + latex: "\\pi", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/miv"].stateValues.value.tree).eqls("pi"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("\\pi"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + "pi", + ); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/miv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "3.141592654", + ); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + Math.PI, + ); + + // type x + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 3.141592654, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("x"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(Math.PI); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls("x"); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(0); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(0); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("0"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(0); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(0); + + // type 2/3 + + await updateMathInputImmediateValue({ + latex: "2/3", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(0); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(["/", 2, 3]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("2/3"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(0); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "/", + 2, + 3, + ]); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/mv"].stateValues.valueForDisplay.tree).eqls( + 0.6666666667, + ); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/miv"].stateValues.valueForDisplay.tree).eqls( + 0.6666666667, + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "0.6666666667", + ); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(2 / 3); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + 2 / 3, + ); + }); + + it("mathinput with number child, force positive integer", async () => { + let core = await createTestCore({ + doenetML: ` +

+ +

+

Value: $mi.value{assignNames="mv"}

+

Immediate Value: $mi.immediateValue{assignNames="miv"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls(""); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(NaN); + + // type a number + + await updateMathInputImmediateValue({ + latex: "5", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("5"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(5); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("5"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(5); + + // type pi + + await updateMathInputImmediateValue({ + latex: "\\pi", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(5); + expect(stateVariables["/miv"].stateValues.value.tree).eqls("pi"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("\\pi"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(5); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + "pi", + ); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(3); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(3); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("3"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(3); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(3); + + // type x + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(3); + expect(stateVariables["/miv"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("x"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(3); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls("x"); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls(""); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(NaN); + + // type 2/3 + + await updateMathInputImmediateValue({ + latex: "2/3", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(["/", 2, 3]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("2/3"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "/", + 2, + 3, + ]); + + // update value (e.g., hit enter) + + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mv"].stateValues.value.tree).eqls(1); + expect(stateVariables["/miv"].stateValues.value.tree).eqls(1); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("1"); + expect(stateVariables["/mi"].stateValues.value.tree).eqls(1); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls(1); + }); + + it("copy raw renderer value, handle incomplete math", async () => { + let core = await createTestCore({ + doenetML: ` + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mi"].stateValues.value.tree).eqls("\uff3f"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + "\uff3f", + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls(""); + expect(stateVariables["/rv"].stateValues.value).eqls(""); + + // enter value that parses to math + await updateMathInputValue({ + latex: "a", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls("a"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls("a"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("a"); + expect(stateVariables["/rv"].stateValues.value).eqls("a"); + + // enter value that is incomplete in math + + await updateMathInputValue({ + latex: "a^{ }", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "^", + "a", + "\uff3f", + ]); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "^", + "a", + "\uff3f", + ]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "a^{ }", + ); + expect(stateVariables["/rv"].stateValues.value).eqls("a^{ }"); + + // still have incomplete math + + await updateMathInputValue({ + latex: "a^{bc+}", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "^", + "a", + ["+", ["*", "b", "c"], "\uff3f"], + ]); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "^", + "a", + ["+", ["*", "b", "c"], "\uff3f"], + ]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "a^{bc+}", + ); + expect(stateVariables["/rv"].stateValues.value).eqls("a^{bc+}"); + + // complete to valid math + + await updateMathInputValue({ + latex: "a^{bc+d}", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "^", + "a", + ["+", ["*", "b", "c"], "d"], + ]); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "^", + "a", + ["+", ["*", "b", "c"], "d"], + ]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "a^{bc+d}", + ); + expect(stateVariables["/rv"].stateValues.value).eqls("a^{bc+d}"); + + // incomplete math again + + await updateMathInputValue({ + latex: "a^{bc+d}-", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "+", + ["^", "a", ["+", ["*", "b", "c"], "d"]], + ["-", "\uff3f"], + ]); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "+", + ["^", "a", ["+", ["*", "b", "c"], "d"]], + ["-", "\uff3f"], + ]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "a^{bc+d}-", + ); + expect(stateVariables["/rv"].stateValues.value).eqls("a^{bc+d}-"); + + // complete to valid math again + + await updateMathInputValue({ + latex: "a^{bc+d}-e", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "+", + ["^", "a", ["+", ["*", "b", "c"], "d"]], + ["-", "e"], + ]); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "+", + ["^", "a", ["+", ["*", "b", "c"], "d"]], + ["-", "e"], + ]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( + "a^{bc+d}-e", + ); + expect(stateVariables["/rv"].stateValues.value).eqls("a^{bc+d}-e"); + }); + + it("copy raw renderer value, handle invalid math", async () => { + let core = await createTestCore({ + doenetML: ` + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mi"].stateValues.value.tree).eqls("\uff3f"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + "\uff3f", + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls(""); + expect(stateVariables["/rv"].stateValues.value).eqls(""); + + // enter value that parses to math + await updateMathInputValue({ + latex: "a", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls("a"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls("a"); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("a"); + expect(stateVariables["/rv"].stateValues.value).eqls("a"); + + // enter value that is error in math + + await updateMathInputValue({ + latex: "a@", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls("\uff3f"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + "\uff3f", + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("a@"); + expect(stateVariables["/rv"].stateValues.value).eqls("a@"); + + // still have error in math + + await updateMathInputValue({ + latex: "ab+@", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls("\uff3f"); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls( + "\uff3f", + ); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("ab+@"); + expect(stateVariables["/rv"].stateValues.value).eqls("ab+@"); + + // make valid math + + await updateMathInputValue({ + latex: "ab+c", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "+", + ["*", "a", "b"], + "c", + ]); + expect(stateVariables["/mi"].stateValues.immediateValue.tree).eqls([ + "+", + ["*", "a", "b"], + "c", + ]); + expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls("ab+c"); + expect(stateVariables["/rv"].stateValues.value).eqls("ab+c"); + }); + + it("parse scientific notation", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("5E+1"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + ["*", 5, "E"], + 1, + ]); + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + ["*", 5, "E"], + 1, + ]); + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("5E+1"); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls(50); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(50); + + await updateMathInputValue({ + latex: "2x-3E+2", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi1"].stateValues.rawRendererValue), + ).eq("2x-3E+2"); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + ["-", ["*", 3, "E"]], + 2, + ]); + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + ["-", ["*", 3, "E"]], + 2, + ]); + + await updateMathInputValue({ + latex: "2x-3E+2", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/mi2"].stateValues.rawRendererValue), + ).eq("2x-3E+2"); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + -300, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + -300, + ]); + }); + + it("remove strings", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("\uff3f"); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls("\uff3f"); + expect(stateVariables["/mi3"].stateValues.value.tree).eqls("\uff3f"); + + await updateMathInputValue({ + latex: "12,345", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "12,345", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "12,345", + componentName: "/mi3", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi1"].stateValues.value.tree).eq(12345); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "list", + 12, + 345, + ]); + expect(stateVariables["/mi3"].stateValues.value.tree).eq(12345); + + await updateMathInputValue({ + latex: "\\$45.23", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "\\$45.23", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "\\$45.23", + componentName: "/mi3", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "unit", + "$", + 45.23, + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(45.23); + expect(stateVariables["/mi3"].stateValues.value.tree).eq(45.23); + + await updateMathInputValue({ + latex: "78\\%", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "78\\%", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "78\\%", + componentName: "/mi3", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "unit", + 78, + "%", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(78); + expect(stateVariables["/mi3"].stateValues.value.tree).eq(78); + + await updateMathInputValue({ + latex: "\\$34,000\\%dx", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "\\$34,000\\%dx", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "\\$34,000\\%dx", + componentName: "/mi3", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "unit", + "$", + ["*", ["unit", 34000, "%"], "d", "x"], + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "list", + 34, + ["*", 0, "d", "x"], + ]); + expect(stateVariables["/mi3"].stateValues.value.tree).eq(34000); + }); + + it("mathinput updates not messed up with invalid child logic containing a composite", async () => { + let core = await createTestCore({ + doenetML: ` +
    + x $m +
  1. +
+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m"].stateValues.value.tree).eqls("x"); + + await updateMathInputValue({ + latex: "\\sqrt{4}", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.value.tree).eqls([ + "apply", + "sqrt", + 4, + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "apply", + "sqrt", + 4, + ]); + }); + + it("valueChanged", async () => { + let doenetML = ` +

+

+

+

$mi2.immediateValue

+ + `; + + let core = await createTestCore({ + doenetML, + }); + + 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 + + await updateMathInputImmediateValue({ + latex: "y", + 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 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); + + // type in second marks only second immediate value as changed + await updateMathInputImmediateValue({ + latex: "z", + 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); + + // press enter in second marks only second value as changed + 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); + + // type in third marks third immediate value as changed + + await updateMathInputImmediateValue({ + latex: "a", + 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); + + // press enter in third marks third value as changed + + 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); + + // type in fourth marks fourth immediate value as changed + + await updateMathInputImmediateValue({ + latex: "b", + 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 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); + + // reload + + core = await createTestCore({ + 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); + + // type in third marks only third immediate value as changed + + await updateMathInputImmediateValue({ + latex: "y", + 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); + + // press enter in third marks first and third value/immediateValue as changed + + 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); + + // type in fourth marks only fourth immediate value as changed + + await updateMathInputImmediateValue({ + latex: "z", + 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 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); + }); + + it("math input with label", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mi1"].stateValues.label).eq("Type something"); + expect(stateVariables["/mi2"].stateValues.label).eq( + "Hello \\(\\frac{a}{b}\\)", + ); + }); + + it("bound to fixed math", async () => { + // Verify that fixed bug + // where deleting the mathinput contents wasn't restored on enter + let core = await createTestCore({ + doenetML: ` + 1 +

$m + , + , +

+

+ , + , +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1rv"].stateValues.value).eq("1"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2rv"].stateValues.value).eq("1"); + + // Delete contents from mathinput 1 + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq( + "\uff3f", + ); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/mi1rv"].stateValues.value).eq(""); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2rv"].stateValues.value).eq("1"); + + // Contents of mathinput 1 restored on enter + + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1rv"].stateValues.value).eq("1"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2rv"].stateValues.value).eq("1"); + + // Add contents to mathinput 1 + + await updateMathInputImmediateValue({ + latex: "12", + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq(12); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq(12); + expect(stateVariables["/mi1rv"].stateValues.value).eq("12"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2rv"].stateValues.value).eq("1"); + + // Contents of mathinput 1 restored on enter + + await updateMathInputValueToImmediateValue({ + componentName: "/mi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1rv"].stateValues.value).eq("1"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2rv"].stateValues.value).eq("1"); + + // Delete contents from mathinput 2 + + await updateMathInputImmediateValue({ + latex: "", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1rv"].stateValues.value).eq("1"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq( + "\uff3f", + ); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/mi2rv"].stateValues.value).eq(""); + + // Contents of mathinput 2 restored on enter + + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1rv"].stateValues.value).eq("1"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2rv"].stateValues.value).eq("1"); + + // Add contents to mathinput 2 + + await updateMathInputImmediateValue({ + latex: "12", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1rv"].stateValues.value).eq("1"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq(12); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(12); + expect(stateVariables["/mi2rv"].stateValues.value).eq("12"); + + // Contents of mathinput 2 restored on enter + + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi1v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi1rv"].stateValues.value).eq("1"); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2"].stateValues.immediateValue.tree).eq(1); + expect(stateVariables["/mi2v"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(1); + expect(stateVariables["/mi2rv"].stateValues.value).eq("1"); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/mathoperators.test.ts b/packages/doenetml-worker/src/test/tagSpecific/mathoperators.test.ts new file mode 100644 index 000000000..dbaf4120f --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/mathoperators.test.ts @@ -0,0 +1,7782 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import me from "math-expressions"; +import { updateMathInputValue } from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Math operator tests", async () => { + it("sum", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 6/2175-4 + 6/2175-4 + 6/2175-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(21); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eqls(["+", 3, 17, 1]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(21); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(21); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eqls(["+", 3, 17, 1]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(21); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eqls(["+", ["/", 6, 2], 17, 1]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(21); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(21); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberSum"].stateValues.value.tree).eq(21); + expect( + stateVariables["/withNumberSum"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberSum"].stateValues.isNumber).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + "y", + "x", + "y", + "z", + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + ["*", 2, "y"], + "z", + ]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(21); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsb"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + "y", + "x", + "y", + "z", + ]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("sum with sugar", async () => { + let core = await createTestCore({ + doenetML: ` + 3 + 17 + 5-4 + 3 + 6/2 + 3175-4 + 3 17 1 + 3 17 1 + 3 17 1 + 6/2 17 5-4 + 6/2 17 5-4 + 6/2 17 5-4 + $a$b$c + $a$b$c + $a$b$c + $a $b $c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + xx+yx+y+z + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(21); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.value.tree).eq( + 21, + ); + expect( + stateVariables["/numbersAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues.value + .tree, + ).eqls(["+", 3, 17, 1]); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(21); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numericAsString"].stateValues.value.tree).eqls([ + "+", + ["/", 6, 2], + 17, + 5, + -4, + ]); + expect( + stateVariables["/numericAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/numericAsString"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.value.tree, + ).eq(21); + expect( + stateVariables["/numericAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.value + .tree, + ).eq(21); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.value.tree).eq( + 21, + ); + expect( + stateVariables["/numbersAsMacros"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues.value + .tree, + ).eqls(["+", 3, 17, 1]); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(21); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.value.tree).eq( + 21, + ); + expect( + stateVariables["/numbersAsMacros2"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacro"].stateValues.value.tree, + ).eq(21); + expect( + stateVariables["/withNumberMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMathMacro"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .value.tree, + ).eqls(["+", 3, 17, 1]); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(21); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacro"].stateValues.value.tree, + ).eqls(["+", ["/", 6, 2], 17, 1]); + expect( + stateVariables["/withNumericMathMacro"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/withNumericMathMacro"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues.value + .tree, + ).eq(21); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .value.tree, + ).eq(21); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + "y", + "x", + "y", + "z", + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsAsString"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + "y", + "x", + "y", + "z", + ]); + expect( + stateVariables["/varsAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsAsStringSimplify"].stateValues.value.tree, + ).eqls(["+", ["*", 3, "x"], ["*", 2, "y"], "z"]); + expect( + stateVariables["/varsAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsStringSimplify"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.isNumber, + ).eq(false); + }); + + it("sum as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 3 + 17 + 5-4 + + sum(3,17,5-4) + sum(3,17,5-4) + sum(3 17 5-4) + sum(3 17 5-4) + + sum(3,17,5-4) + + + sum(3,17,5-4) + + + sum(3175-4) + + + sum(3175-4) + + + sum($a,$b,$c) + + + sum($a,$b,$c) + + + sum($a$b$c) + + + sum($a$b$c) + + + sum($nums) + + + sum($nums) + sum($nums) + + + sum($nums) + + + sum($nums, $a, $b, $c) + + + sum($nums, $a, $b, $c) + + + sum($a, $b, $c, $nums) + + + sum($a, $b, $c, $nums) + + + sum($a, $b, $nums, $c) + + + sum($a, $b, $nums, $c) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "sum", + ["tuple", 3, 17, ["+", 5, -4]], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(21); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numberStringProduct"].stateValues.value.tree, + ).eqls(["apply", "sum", ["+", ["*", 3, 17, 5], -4]]); + expect(stateVariables["/numberStringProduct"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.value + .tree, + ).eq(251); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "sum", ["tuple", 3, 17, 1]]); + expect( + await await stateVariables["/numberComponentsCommas"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(21); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numberComponentsProduct"].stateValues.value.tree, + ).eqls(["apply", "sum", ["*", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsProduct"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "sum", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(21); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/macrosProduct"].stateValues.value.tree).eqls([ + "apply", + "sum", + ["*", 3, 17, 1], + ]); + expect(stateVariables["/macrosProduct"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosProductSimplify"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/macrosProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "sum", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlusGroup"].stateValues.value.tree).eqls([ + "+", + ["apply", "sum", ["tuple", 3, 17, 1]], + ["apply", "sum", ["tuple", 3, 17, 1]], + ]); + expect(stateVariables["/groupPlusGroup"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq(21); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + + expect(stateVariables["/groupPlus"].stateValues.value.tree).eqls([ + "apply", + "sum", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlusSimplify"].stateValues.value.tree).eq( + 42, + ); + expect(stateVariables["/groupPlusSimplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus2"].stateValues.value.tree).eqls([ + "apply", + "sum", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus2Simplify"].stateValues.value.tree).eq( + 42, + ); + expect(stateVariables["/groupPlus2Simplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus3"].stateValues.value.tree).eqls([ + "apply", + "sum", + ["tuple", 3, 17, 3, 17, 1, 1], + ]); + expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus3Simplify"].stateValues.value.tree).eq( + 42, + ); + expect(stateVariables["/groupPlus3Simplify"].stateValues.isNumber).eq( + true, + ); + }); + + it("sum with lists", async () => { + let core = await createTestCore({ + doenetML: ` + 3 17 5-4 + 3 17 5-4 + 3 17 5-4 + 317 5-4 + 317 5-4 + 317 5-4 + 6/217 5-4 + 6/217 5-4 + 6/217 5-4 + 317 5-4 + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(21); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eqls(["+", 3, 17, 1]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(21); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(21); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eqls(["+", 3, 17, 1]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(21); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eqls(["+", ["/", 6, 2], 17, 1]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(21); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(21); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberSum"].stateValues.value.tree).eq(21); + expect( + stateVariables["/withNumberSum"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberSum"].stateValues.isNumber).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + "y", + "x", + "y", + "z", + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.value.tree).eqls([ + "+", + ["*", 3, "x"], + ["*", 2, "y"], + "z", + ]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(21); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsb"].stateValues.value.tree).eqls([ + "+", + "x", + "x", + "y", + "x", + "y", + "z", + ]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("product", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 6/2175-4 + 6/2175-4 + 6/2175-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(51); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eqls(["*", 3, 17, 1]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eqls(["*", 3, 17, 1]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eqls(["*", ["/", 6, 2], 17, 1]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(51); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberProduct"].stateValues.value.tree).eq( + 51, + ); + expect( + stateVariables["/withNumberProduct"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberProduct"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "*", + "x", + ["+", "x", "y"], + ["+", "x", "y", "z"], + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsExpand"].stateValues.value.tree).eqls([ + "+", + ["^", "x", 3], + ["*", 2, "y", ["^", "x", 2]], + ["*", "z", ["^", "x", 2]], + ["*", "x", ["^", "y", 2]], + ["*", "x", "y", "z"], + ]); + expect(stateVariables["/varsExpand"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsExpand"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(51); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsb"].stateValues.value.tree).eqls([ + "*", + "x", + ["+", "x", "y"], + ["+", "x", "y", "z"], + ]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("product with sugar", async () => { + let core = await createTestCore({ + doenetML: ` + 3 + 17 + 5-4 + 3 + 6/2 + 3175-4 + 3 17 1 + 3 17 1 + 3 17 1 + 6/2 17 5-4 + 6/2 17 5-4 + 6/2 17 5-4 + $a$b$c + $a$b$c + $a$b$c + $a $b $c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + xx+yx+y+z + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(51); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.value.tree).eq( + 51, + ); + expect( + stateVariables["/numbersAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues.value + .tree, + ).eqls(["*", 3, 17, 1]); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(51); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numericAsString"].stateValues.value.tree).eqls([ + "*", + ["/", 6, 2], + 17, + ["+", 5, -4], + ]); + expect( + stateVariables["/numericAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/numericAsString"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/numericAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.value.tree).eq( + 51, + ); + expect( + stateVariables["/numbersAsMacros"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues.value + .tree, + ).eqls(["*", 3, 17, 1]); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(51); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.value.tree).eq( + 51, + ); + expect( + stateVariables["/numbersAsMacros2"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacro"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/withNumberMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMathMacro"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .value.tree, + ).eqls(["*", 3, 17, 1]); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacro"].stateValues.value.tree, + ).eqls(["*", ["/", 6, 2], 17, 1]); + expect( + stateVariables["/withNumericMathMacro"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/withNumericMathMacro"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .value.tree, + ).eq(51); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "*", + "x", + ["+", "x", "y"], + ["+", "x", "y", "z"], + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsAsString"].stateValues.value.tree).eqls([ + "*", + "x", + ["+", "x", "y"], + ["+", "x", "y", "z"], + ]); + expect( + stateVariables["/varsAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsAsStringExpand"].stateValues.value.tree, + ).eqls([ + "+", + ["^", "x", 3], + ["*", 2, "y", ["^", "x", 2]], + ["*", "z", ["^", "x", 2]], + ["*", "x", ["^", "y", 2]], + ["*", "x", "y", "z"], + ]); + expect( + stateVariables["/varsAsStringExpand"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsStringExpand"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.isNumber, + ).eq(false); + }); + + it("prod as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 3 + 17 + 5-4 + + prod(3,17,5-4) + prod(3,17,5-4) + prod(3 17 5-4) + prod(3 17 5-4) + + prod(3,17,5-4) + + + prod(3,17,5-4) + + + prod(3175-4) + + + prod(3175-4) + + + prod($a,$b,$c) + + + prod($a,$b,$c) + + + prod($a$b$c) + + + prod($a$b$c) + + + prod($nums) + + + prod($nums) + + + prod($nums, $a, $b, $c) + + + prod($nums, $a, $b, $c) + + + prod($a, $b, $c, $nums) + + + prod($a, $b, $c, $nums) + + + prod($a, $b, $nums, $c) + + + prod($a, $b, $nums, $c) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "prod", + ["tuple", 3, 17, ["+", 5, -4]], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(51); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numberStringProduct"].stateValues.value.tree, + ).eqls(["apply", "prod", ["+", ["*", 3, 17, 5], -4]]); + expect(stateVariables["/numberStringProduct"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.value + .tree, + ).eq(251); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "prod", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsCommas"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numberComponentsProduct"].stateValues.value.tree, + ).eqls(["apply", "prod", ["*", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsProduct"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "prod", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(51); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/macrosProduct"].stateValues.value.tree).eqls([ + "apply", + "prod", + ["*", 3, 17, 1], + ]); + expect(stateVariables["/macrosProduct"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosProductSimplify"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/macrosProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "prod", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq(51); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + + expect(stateVariables["/groupPlus"].stateValues.value.tree).eqls([ + "apply", + "prod", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlusSimplify"].stateValues.value.tree).eq( + 2601, + ); + expect(stateVariables["/groupPlusSimplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus2"].stateValues.value.tree).eqls([ + "apply", + "prod", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus2Simplify"].stateValues.value.tree).eq( + 2601, + ); + expect(stateVariables["/groupPlus2Simplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus3"].stateValues.value.tree).eqls([ + "apply", + "prod", + ["tuple", 3, 17, 3, 17, 1, 1], + ]); + expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus3Simplify"].stateValues.value.tree).eq( + 2601, + ); + expect(stateVariables["/groupPlus3Simplify"].stateValues.isNumber).eq( + true, + ); + }); + + it("product with lists", async () => { + let core = await createTestCore({ + doenetML: ` + 3 17 5-4 + 3 17 5-4 + 3 17 5-4 + 317 5-4 + 317 5-4 + 317 5-4 + 6/217 5-4 + 6/217 5-4 + 6/217 5-4 + 317 5-4 + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(51); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eqls(["*", 3, 17, 1]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eqls(["*", 3, 17, 1]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eqls(["*", ["/", 6, 2], 17, 1]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(51); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberProduct"].stateValues.value.tree).eq( + 51, + ); + expect( + stateVariables["/withNumberProduct"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberProduct"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "*", + "x", + ["+", "x", "y"], + ["+", "x", "y", "z"], + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsExpand"].stateValues.value.tree).eqls([ + "+", + ["^", "x", 3], + ["*", 2, "y", ["^", "x", 2]], + ["*", "z", ["^", "x", 2]], + ["*", "x", ["^", "y", 2]], + ["*", "x", "y", "z"], + ]); + expect(stateVariables["/varsExpand"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsExpand"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(51); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsb"].stateValues.value.tree).eqls([ + "*", + "x", + ["+", "x", "y"], + ["+", "x", "y", "z"], + ]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("clamp number", async () => { + let core = await createTestCore({ + doenetML: ` + 55.3 + -55.3 + 0.3 + + 55.3 + -55.3 + 12 + + 55.3 + -55.3 + 12 + + x+y + x+y + + 4 + + 12$a + -12$a + 3$a + + $_clampnumber1{name="clampnumber1b"} + $_clampnumber5{name="clampnumber5b"} + $_clampnumber9{name="clampnumber9b"} + $_clampnumber14{name="clampnumber14b"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/_clampnumber1"].stateValues.value.tree).eq(1); + expect(stateVariables["/_clampnumber2"].stateValues.value.tree).eq(0); + expect(stateVariables["/_clampnumber3"].stateValues.value.tree).eq(0.3); + expect(stateVariables["/_clampnumber4"].stateValues.value.tree).eq(40); + expect(stateVariables["/_clampnumber5"].stateValues.value.tree).eq(10); + expect(stateVariables["/_clampnumber6"].stateValues.value.tree).eq(12); + expect(stateVariables["/_clampnumber7"].stateValues.value.tree).eq(40); + expect(stateVariables["/_clampnumber8"].stateValues.value.tree).eq(10); + expect(stateVariables["/_clampnumber9"].stateValues.value.tree).eq(12); + expect(stateVariables["/_clampnumber10"].stateValues.value.tree).eqls( + NaN, + ); + expect(stateVariables["/_clampnumber11"].stateValues.value.tree).eqls( + NaN, + ); + expect(stateVariables["/_clampnumber12"].stateValues.value.tree).eq(40); + expect(stateVariables["/_clampnumber13"].stateValues.value.tree).eq(10); + expect(stateVariables["/_clampnumber14"].stateValues.value.tree).eq(12); + expect(stateVariables["/clampnumber1b"].stateValues.value.tree).eq(1); + expect(stateVariables["/clampnumber5b"].stateValues.value.tree).eq(10); + expect(stateVariables["/clampnumber9b"].stateValues.value.tree).eq(12); + expect(stateVariables["/clampnumber14b"].stateValues.value.tree).eq(12); + expect( + stateVariables["/_clampnumber1"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber2"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber3"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber4"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber5"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber6"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber7"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber8"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber9"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber10"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber11"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber12"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber13"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/_clampnumber14"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/clampnumber1b"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/clampnumber5b"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/clampnumber9b"].stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/clampnumber14b"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/_clampnumber1"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber2"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber3"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber4"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber5"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber6"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber7"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber8"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber9"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber10"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/_clampnumber11"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/_clampnumber12"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber13"].stateValues.isNumber).eq(true); + expect(stateVariables["/_clampnumber14"].stateValues.isNumber).eq(true); + expect(stateVariables["/clampnumber1b"].stateValues.isNumber).eq(true); + expect(stateVariables["/clampnumber5b"].stateValues.isNumber).eq(true); + expect(stateVariables["/clampnumber9b"].stateValues.isNumber).eq(true); + expect(stateVariables["/clampnumber14b"].stateValues.isNumber).eq(true); + }); + + it("wrap number periodic", async () => { + let core = await createTestCore({ + doenetML: ` + 55.3 + -55.3 + 0.3 + + 55.3 + -55.3 + 12 + + 55.3 + -55.3 + 12 + + x+y + x+y + + 4 + + 12$a + -12$a + 3$a + + $_wrapnumberperiodic1{name="wrapnumberperiodic1b"} + $_wrapnumberperiodic5{name="wrapnumberperiodic5b"} + $_wrapnumberperiodic9{name="wrapnumberperiodic9b"} + $_wrapnumberperiodic14{name="wrapnumberperiodic14b"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/_wrapnumberperiodic1"].stateValues.value.tree, + ).closeTo(0.3, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic2"].stateValues.value.tree, + ).closeTo(0.7, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic3"].stateValues.value.tree, + ).closeTo(0.3, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic4"].stateValues.value.tree, + ).closeTo(25.3, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic5"].stateValues.value.tree, + ).closeTo(34.7, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic6"].stateValues.value.tree, + ).closeTo(12, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic7"].stateValues.value.tree, + ).closeTo(25.3, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic8"].stateValues.value.tree, + ).closeTo(34.7, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic9"].stateValues.value.tree, + ).closeTo(12, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic10"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/_wrapnumberperiodic11"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/_wrapnumberperiodic12"].stateValues.value.tree, + ).closeTo(18, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic13"].stateValues.value.tree, + ).closeTo(12, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic14"].stateValues.value.tree, + ).closeTo(12, 1e-12); + expect( + stateVariables["/wrapnumberperiodic1b"].stateValues.value.tree, + ).closeTo(0.3, 1e-12); + expect( + stateVariables["/wrapnumberperiodic5b"].stateValues.value.tree, + ).closeTo(34.7, 1e-12); + expect( + stateVariables["/wrapnumberperiodic9b"].stateValues.value.tree, + ).closeTo(12, 1e-12); + expect( + stateVariables["/wrapnumberperiodic14b"].stateValues.value.tree, + ).closeTo(12, 1e-12); + expect( + stateVariables["/_wrapnumberperiodic1"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic2"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic3"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic4"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic5"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic6"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic7"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic8"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic9"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic10"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic11"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic12"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic13"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic14"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/wrapnumberperiodic1b"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/wrapnumberperiodic5b"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/wrapnumberperiodic9b"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/wrapnumberperiodic14b"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/_wrapnumberperiodic1"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/_wrapnumberperiodic2"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/_wrapnumberperiodic3"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/_wrapnumberperiodic4"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/_wrapnumberperiodic5"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/_wrapnumberperiodic6"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/_wrapnumberperiodic7"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/_wrapnumberperiodic8"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/_wrapnumberperiodic9"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/_wrapnumberperiodic10"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/_wrapnumberperiodic11"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/_wrapnumberperiodic12"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic13"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/_wrapnumberperiodic14"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/wrapnumberperiodic1b"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/wrapnumberperiodic5b"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/wrapnumberperiodic9b"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/wrapnumberperiodic14b"].stateValues.isNumber, + ).eq(true); + }); + + it("clamp and wrap number updatable", async () => { + let core = await createTestCore({ + doenetML: ` + + (6,7) + + ( + $P1.x + , + + $P1.y + + ) + + ($P2.y, $P2.x) + + + $graph1{name="g2"} + `, + }); + + let clamp = (x) => Math.min(5, Math.max(-2, x)); + let wrap = (x) => -2 + me.math.mod(x + 2, 7); + + let stateVariables = await returnAllStateVariables(core); + let x = 6, + y = 7; + 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(clamp(x)); + expect(stateVariables["/P2"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[0].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[1].tree).eq(clamp(x)); + + let g2children = stateVariables["/g2"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect((await g2children[0].stateValues.xs)[0].tree).eq(x); + expect((await g2children[0].stateValues.xs)[1].tree).eq(y); + expect((await g2children[1].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[1].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[0].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[1].tree).eq(clamp(x)); + + // move point 1 + x = -5; + y = 0; + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x, y }, + event: null, + }); + 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(clamp(x)); + expect(stateVariables["/P2"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[0].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[1].tree).eq(clamp(x)); + + g2children = stateVariables["/g2"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect((await g2children[0].stateValues.xs)[0].tree).eq(x); + expect((await g2children[0].stateValues.xs)[1].tree).eq(y); + expect((await g2children[1].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[1].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[0].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[1].tree).eq(clamp(x)); + + // move point 2 + x = 9; + y = -3; + await core.requestAction({ + actionName: "movePoint", + componentName: "/P2", + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/P1"].stateValues.xs[0].tree).eq(clamp(x)); + expect(stateVariables["/P1"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P2"].stateValues.xs[0].tree).eq(clamp(x)); + expect(stateVariables["/P2"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[0].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[1].tree).eq(clamp(x)); + + g2children = stateVariables["/g2"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect((await g2children[0].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[0].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[1].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[1].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[0].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[1].tree).eq(clamp(x)); + + // move point 3 + x = -4; + y = 8; + await core.requestAction({ + actionName: "movePoint", + componentName: "/P3", + args: { x: y, y: x }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/P1"].stateValues.xs[0].tree).eq(clamp(x)); + expect(stateVariables["/P1"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P2"].stateValues.xs[0].tree).eq(clamp(x)); + expect(stateVariables["/P2"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[0].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[1].tree).eq(clamp(x)); + + g2children = stateVariables["/g2"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect((await g2children[0].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[0].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[1].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[1].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[0].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[1].tree).eq(clamp(x)); + + // move point 4 + x = 10; + y = -10; + + await core.requestAction({ + actionName: "movePoint", + componentName: + stateVariables["/g2"].activeChildren[0].componentName, + args: { x, y }, + event: null, + }); + + 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(clamp(x)); + expect(stateVariables["/P2"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[0].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[1].tree).eq(clamp(x)); + + g2children = stateVariables["/g2"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect((await g2children[0].stateValues.xs)[0].tree).eq(x); + expect((await g2children[0].stateValues.xs)[1].tree).eq(y); + expect((await g2children[1].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[1].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[0].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[1].tree).eq(clamp(x)); + + // move point 5 + x = 11; + y = -13; + + await core.requestAction({ + actionName: "movePoint", + componentName: + stateVariables["/g2"].activeChildren[1].componentName, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs[0].tree).eq(clamp(x)); + expect(stateVariables["/P1"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P2"].stateValues.xs[0].tree).eq(clamp(x)); + expect(stateVariables["/P2"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[0].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[1].tree).eq(clamp(x)); + + g2children = stateVariables["/g2"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect((await g2children[0].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[0].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[1].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[1].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[0].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[1].tree).eq(clamp(x)); + + // move point 6 + x = -3; + y = 12; + + await core.requestAction({ + actionName: "movePoint", + componentName: + stateVariables["/g2"].activeChildren[2].componentName, + args: { x: y, y: x }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs[0].tree).eq(clamp(x)); + expect(stateVariables["/P1"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P2"].stateValues.xs[0].tree).eq(clamp(x)); + expect(stateVariables["/P2"].stateValues.xs[1].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[0].tree).eq(wrap(y)); + expect(stateVariables["/P3"].stateValues.xs[1].tree).eq(clamp(x)); + + g2children = stateVariables["/g2"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect((await g2children[0].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[0].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[1].stateValues.xs)[0].tree).eq(clamp(x)); + expect((await g2children[1].stateValues.xs)[1].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[0].tree).eq(wrap(y)); + expect((await g2children[2].stateValues.xs)[1].tree).eq(clamp(x)); + }); + + it("round", async () => { + let core = await createTestCore({ + doenetML: ` + 55.3252326 + log(31) + 0.5 + + 55.3252326 + log(31) + 0.5555 + + 55.3252326 + log(31) + 0.555555 + + sin(55.3252326 x) + log(31) exp(3) sin(2) + + exp(20) pi + + $_round1{name="round1b"} + $_round5{name="round5b"} + $_round11{name="round11b"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/_round1"].stateValues.value.tree).eq(55); + expect(stateVariables["/_round2"].stateValues.value.tree).eq(3); + expect(stateVariables["/_round3"].stateValues.value.tree).eq(1); + expect(stateVariables["/_round4"].stateValues.value.tree).eq(55.3); + expect(stateVariables["/_round5"].stateValues.value.tree).eq(3.43); + expect(stateVariables["/_round6"].stateValues.value.tree).eq(0.556); + expect(stateVariables["/_round7"].stateValues.value.tree).eq(55.3); + expect(stateVariables["/_round8"].stateValues.value.tree).eq(3.434); + expect(stateVariables["/_round9"].stateValues.value.tree).eq(0.55556); + expect(stateVariables["/_round10"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 55.3, "x"], + ]); + expect(stateVariables["/_round11"].stateValues.value.tree).eq(62.7); + expect(stateVariables["/_round12"].stateValues.value.tree).eq( + 1524000000, + ); + expect(stateVariables["/round1b"].stateValues.value.tree).eq(55); + expect(stateVariables["/round5b"].stateValues.value.tree).eq(3.43); + expect(stateVariables["/round11b"].stateValues.value.tree).eq(62.7); + }); + + it("round ignores display rounding of math children", async () => { + let core = await createTestCore({ + doenetML: ` + 55.3252326 + 55.3252326 + 55.3252326 + 55.3252326 + + 55.3252326 + 55.3252326 + 55.3252326 + 55.3252326 + + + + + + + + + + + + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/_round1"].stateValues.value.tree).eqls(55.3252); + + expect(stateVariables["/_round2"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/_round3"].stateValues.value.tree).eqls( + 55.325233, + ); + expect(stateVariables["/_round4"].stateValues.value.tree).eqls( + 55.325233, + ); + + expect(stateVariables["/_round5"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/_round6"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/_round7"].stateValues.value.tree).eqls( + 55.325233, + ); + expect(stateVariables["/_round8"].stateValues.value.tree).eqls( + 55.325233, + ); + + expect(stateVariables["/r1a"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/r2a"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/r3a"].stateValues.value.tree).eqls(55.325233); + expect(stateVariables["/r4a"].stateValues.value.tree).eqls(55.325233); + + expect(stateVariables["/r5a"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/r6a"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/r7a"].stateValues.value.tree).eqls(55.325233); + expect(stateVariables["/r8a"].stateValues.value.tree).eqls(55.325233); + + expect(stateVariables["/r1b"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/r2b"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/r3b"].stateValues.value.tree).eqls(55.325233); + expect(stateVariables["/r4b"].stateValues.value.tree).eqls(55.325233); + + expect(stateVariables["/r5b"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/r6b"].stateValues.value.tree).eqls(55.3252); + expect(stateVariables["/r7b"].stateValues.value.tree).eqls(55.325233); + expect(stateVariables["/r8b"].stateValues.value.tree).eqls(55.325233); + }); + + it("convert set to list", async () => { + let core = await createTestCore({ + doenetML: ` +

{1,2,3,2,1}

+

(1,2,3,2,1)

+

1,2,3,2,1

+ +

$_math1

+

$_math2

+

$_math3

+ +

$_convertsettolist1{name="r1"}

+

$_convertsettolist2{name="r2"}

+

$_convertsettolist3{name="r3"}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "set", + 1, + 2, + 3, + 2, + 1, + ]); + expect(stateVariables["/_math2"].stateValues.value.tree).eqls([ + "tuple", + 1, + 2, + 3, + 2, + 1, + ]); + expect(stateVariables["/_math3"].stateValues.value.tree).eqls([ + "list", + 1, + 2, + 3, + 2, + 1, + ]); + expect( + stateVariables["/_convertsettolist1"].stateValues.value.tree, + ).eqls(["list", 1, 2, 3]); + expect( + stateVariables["/_convertsettolist2"].stateValues.value.tree, + ).eqls(["tuple", 1, 2, 3, 2, 1]); + expect( + stateVariables["/_convertsettolist3"].stateValues.value.tree, + ).eqls(["list", 1, 2, 3, 2, 1]); + expect(stateVariables["/r1"].stateValues.value.tree).eqls([ + "list", + 1, + 2, + 3, + ]); + expect(stateVariables["/r2"].stateValues.value.tree).eqls([ + "tuple", + 1, + 2, + 3, + 2, + 1, + ]); + expect(stateVariables["/r3"].stateValues.value.tree).eqls([ + "list", + 1, + 2, + 3, + 2, + 1, + ]); + expect(stateVariables["/_convertsettolist1"].stateValues.unordered).eq( + true, + ); + expect(stateVariables["/_convertsettolist2"].stateValues.unordered).eq( + true, + ); + expect(stateVariables["/_convertsettolist3"].stateValues.unordered).eq( + true, + ); + expect(stateVariables["/r1"].stateValues.unordered).eq(true); + expect(stateVariables["/r2"].stateValues.unordered).eq(true); + expect(stateVariables["/r3"].stateValues.unordered).eq(true); + }); + + it("convert set to list, initially unresolved", async () => { + let core = await createTestCore({ + doenetML: ` +

7 + +

+ +

{$m,$n,$p,$m}

+

$_convertsettolist1{name="csl2"}

+ +

$n3{name="n2"} + $num1{name="n"} + $n2+$num2 + $n3+$num3 + $num3{name="n3"} + 1

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let p = await stateVariables["/p"].stateValues.value; + expect( + stateVariables["/_convertsettolist1"].stateValues.value.tree, + ).eqls(["list", 7, 3, p]); + expect(stateVariables["/csl2"].stateValues.value.tree).eqls([ + "list", + 7, + 3, + p, + ]); + expect(stateVariables["/_convertsettolist1"].stateValues.unordered).eq( + true, + ); + expect(stateVariables["/csl2"].stateValues.unordered).eq(true); + }); + + it("floor and ceil", async () => { + let core = await createTestCore({ + doenetML: ` + 55.3252326 + log(31) + + $_floor1/$_ceil1 + $_ceil1/$_floor1 + +

Allow for slight roundoff error: + 3.999999999999999 + -6999.999999999999 +

+ + $_floor2{name="f2a"} + $_ceil2{name="c2a"} + + 2.1x + -3.2y + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/_floor1"].stateValues.value.tree).eq(55); + expect(stateVariables["/_ceil1"].stateValues.value.tree).eq(4); + expect(stateVariables["/_floor2"].stateValues.value.tree).eq(13); + expect(stateVariables["/_ceil2"].stateValues.value.tree).eq(1); + expect(stateVariables["/_floor3"].stateValues.value.tree).eq(4); + expect(stateVariables["/_ceil3"].stateValues.value.tree).eq(-7000); + expect(stateVariables["/f2a"].stateValues.value.tree).eq(13); + expect(stateVariables["/c2a"].stateValues.value.tree).eq(1); + expect(stateVariables["/_floor4"].stateValues.value.tree).eqls([ + "apply", + "floor", + ["*", 2.1, "x"], + ]); + expect(stateVariables["/_ceil4"].stateValues.value.tree).eqls([ + "apply", + "ceil", + ["-", ["*", 3.2, "y"]], + ]); + }); + + it("floor and ceil as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + \\lfloor 55.3252326 \\rfloor + floor(55.3252326) + + + \\lceil \\log(31.1) \\rceil + ceil(log(31.1)) + + + + \\lfloor $floor1/$ceil1 \\rfloor + floor($floor1/$ceil1) + \\lceil $ceil1/$floor1 \\rceil + ceil($ceil1/$floor1) + +

Allow for slight roundoff error: + \\lfloor 3.999999999999999 \\rfloor + floor 3.999999999999999 + \\lceil -6999.999999999999 \\rceil + ceil -6999.999999999999 +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/floor1"].stateValues.value.tree).eqls([ + "apply", + "floor", + 55.3252326, + ]); + expect(stateVariables["/floor2"].stateValues.value.tree).eqls([ + "apply", + "floor", + 55.3252326, + ]); + expect(stateVariables["/floor1simp"].stateValues.value.tree).eq(55); + expect(stateVariables["/floor2simp"].stateValues.value.tree).eq(55); + expect(stateVariables["/ceil1"].stateValues.value.tree).eqls([ + "apply", + "ceil", + ["apply", "log", 31.1], + ]); + expect(stateVariables["/ceil2"].stateValues.value.tree).eqls([ + "apply", + "ceil", + ["apply", "log", 31.1], + ]); + expect(stateVariables["/ceil1simp"].stateValues.value.tree).eq(4); + expect(stateVariables["/ceil2simp"].stateValues.value.tree).eq(4); + expect(stateVariables["/floor3"].stateValues.value.tree).eq(13); + expect(stateVariables["/floor4"].stateValues.value.tree).eq(13); + expect(stateVariables["/ceil3"].stateValues.value.tree).eq(1); + expect(stateVariables["/ceil4"].stateValues.value.tree).eq(1); + expect(stateVariables["/floor5"].stateValues.value.tree).eq(4); + expect(stateVariables["/floor6"].stateValues.value.tree).eq(4); + expect(stateVariables["/ceil5"].stateValues.value.tree).eq(-7000); + expect(stateVariables["/ceil6"].stateValues.value.tree).eq(-7000); + }); + + it("abs", async () => { + let core = await createTestCore({ + doenetML: ` + -5.3 + -x + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_abs1"].stateValues.value.tree).eq(5.3); + expect(stateVariables["/_abs2"].stateValues.value.tree).eqls([ + "apply", + "abs", + ["-", "x"], + ]); + }); + + it("invert abs", async () => { + let core = await createTestCore({ + doenetML: ` + -9 + + $a2.value{assignNames="a3"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a1"].stateValues.value.tree).eq(9); + expect(stateVariables["/a2"].stateValues.value.tree).eq(9); + expect(stateVariables["/a3"].stateValues.value.tree).eq(9); + + await updateMathInputValue({ componentName: "/a2", latex: "-3", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a1"].stateValues.value.tree).eq(0); + expect(stateVariables["/a2"].stateValues.value.tree).eq(0); + expect(stateVariables["/a3"].stateValues.value.tree).eq(0); + + await updateMathInputValue({ componentName: "/a2", latex: "7", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a1"].stateValues.value.tree).eq(7); + expect(stateVariables["/a2"].stateValues.value.tree).eq(7); + expect(stateVariables["/a3"].stateValues.value.tree).eq(7); + + await updateMathInputValue({ componentName: "/a2", latex: "x", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a1"].stateValues.value.tree).eqls([ + "apply", + "abs", + "x", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "abs", + "x", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "abs", + "x", + ]); + + await updateMathInputValue({ componentName: "/a2", latex: "y", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a1"].stateValues.value.tree).eqls([ + "apply", + "abs", + "y", + ]); + expect(stateVariables["/a2"].stateValues.value.tree).eqls([ + "apply", + "abs", + "y", + ]); + expect(stateVariables["/a3"].stateValues.value.tree).eqls([ + "apply", + "abs", + "y", + ]); + }); + + it("floor, ceil, round and abs updatable", async () => { + let core = await createTestCore({ + doenetML: ` + + (6.1,7.6) + + ( + + $_point1.x + , + + $_point1.y + + ) + + ($_point2.y, $_point1.x) + + + $_graph1{name="g2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let g2ChildrenNames = stateVariables["/g2"].activeChildren.map( + (x) => x.componentName, + ); + + let checkPoints = async function (x, y) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/_point1"].stateValues.xs[0].tree).eq(x); + expect(stateVariables["/_point1"].stateValues.xs[1].tree).eq(y); + expect(stateVariables["/_point2"].stateValues.xs[0].tree).eq( + Math.floor(x), + ); + expect(stateVariables["/_point2"].stateValues.xs[1].tree).eq( + Math.ceil(y), + ); + expect(stateVariables["/_point3"].stateValues.xs[0].tree).eq( + Math.abs(Math.ceil(y)), + ); + expect(stateVariables["/_point3"].stateValues.xs[1].tree).eq( + Math.round(x), + ); + + let g2Children = g2ChildrenNames.map((x) => stateVariables[x]); + expect((await g2Children[0].stateValues.xs)[0].tree).eq(x); + expect((await g2Children[0].stateValues.xs)[1].tree).eq(y); + expect((await g2Children[1].stateValues.xs)[0].tree).eq( + Math.floor(x), + ); + expect((await g2Children[1].stateValues.xs)[1].tree).eq( + Math.ceil(y), + ); + expect((await g2Children[2].stateValues.xs)[0].tree).eq( + Math.abs(Math.ceil(y)), + ); + expect((await g2Children[2].stateValues.xs)[1].tree).eq( + Math.round(x), + ); + }; + + await checkPoints(6.1, 7.6); + + // move point 1, positive y + + let x = -5.1; + let y = 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point1", + args: { x, y }, + event: null, + }); + await checkPoints(x, y); + + // move point 1, negative y + + x = -7.9; + y = -5.8; + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point1", + args: { x, y }, + event: null, + }); + await checkPoints(x, y); + + // move point 2, positive y + + x = 3.4; + y = 8.6; + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point2", + args: { x, y }, + event: null, + }); + await checkPoints(x, y); + + // move point 2, negative y + + x = 7.7; + y = -4.4; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point2", + args: { x, y }, + event: null, + }); + await checkPoints(x, y); + + // move point 3, positive x + + x = 9.4; + y = -1.3; + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point3", + args: { x, y }, + event: null, + }); + await checkPoints(y, x); + + // move point 3, negative x + + x = -8.9; + y = -4.6; + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point3", + args: { x, y }, + event: null, + }); + await checkPoints(y, 0); + + // move point 4, positive y + + x = 6.8; + y = 3.7; + + await core.requestAction({ + actionName: "movePoint", + componentName: g2ChildrenNames[0], + args: { x, y }, + event: null, + }); + await checkPoints(x, y); + + // move point 4, negative y + + x = 1.2; + y = -1.4; + await core.requestAction({ + actionName: "movePoint", + componentName: g2ChildrenNames[0], + args: { x, y }, + event: null, + }); + await checkPoints(x, y); + + // move point 5, positive y + + x = -6.6; + y = 3.2; + await core.requestAction({ + actionName: "movePoint", + componentName: g2ChildrenNames[1], + args: { x, y }, + event: null, + }); + await checkPoints(x, y); + + // move point 5, negative y + + x = -4.3; + y = -8.9; + await core.requestAction({ + actionName: "movePoint", + componentName: g2ChildrenNames[1], + args: { x, y }, + event: null, + }); + await checkPoints(x, y); + + // move point 6, positive x + + x = 6.4; + y = 2.3; + await core.requestAction({ + actionName: "movePoint", + componentName: g2ChildrenNames[2], + args: { x, y }, + event: null, + }); + await checkPoints(y, x); + + // move point 6, negative x + + x = -5.6; + y = 7.8; + await core.requestAction({ + actionName: "movePoint", + componentName: g2ChildrenNames[2], + args: { x, y }, + event: null, + }); + await checkPoints(y, 0); + }); + + it("sign", async () => { + let core = await createTestCore({ + doenetML: ` + -5.3 + 63 + 0 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_sign1"].stateValues.value.tree).eq(-1); + expect(stateVariables["/_sign2"].stateValues.value.tree).eq(1); + expect(stateVariables["/_sign3"].stateValues.value.tree).eq(0); + }); + + it("mean", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 6/2175-4 + 6/2175-4 + 6/2175-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(7); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eqls(["/", ["+", 3, 17, 1], 3]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(7); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(7); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eqls(["/", ["+", 3, 17, 1], 3]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(7); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eqls(["/", ["+", ["/", 6, 2], 17, 1], 3]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(7); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(7); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberMean"].stateValues.value.tree).eq(6); + expect( + stateVariables["/withNumberMean"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMean"].stateValues.isNumber).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "/", + ["+", "x", "x", "y", "x", "y", "z"], + 3, + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.value.tree).eqls([ + "/", + ["+", ["*", 3, "x"], ["*", 2, "y"], "z"], + 3, + ]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(7); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsb"].stateValues.value.tree).eqls([ + "/", + ["+", "x", "x", "y", "x", "y", "z"], + 3, + ]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("mean with sugar", async () => { + let core = await createTestCore({ + doenetML: ` + 3 + 17 + 5-4 + 3 + 6/2 + 3175-4 + 3 17 1 + 3 17 1 + 3 17 1 + 6/2 17 5-4 + 6/2 17 5-4 + 6/2 17 5-4 + $a$b$c + $a$b$c + $a$b$c + $a $b $c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + xx+yx+y+z + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(7); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.value.tree).eq(7); + expect( + stateVariables["/numbersAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues.value + .tree, + ).eqls(["/", ["+", 3, 17, 1], 3]); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(7); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numericAsString"].stateValues.value.tree).eqls([ + "/", + ["+", ["/", 6, 2], 17, 5, -4], + 3, + ]); + expect( + stateVariables["/numericAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/numericAsString"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.value.tree, + ).eq(7); + expect( + stateVariables["/numericAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.value + .tree, + ).eq(7); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.value.tree).eq(7); + expect( + stateVariables["/numbersAsMacros"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues.value + .tree, + ).eqls(["/", ["+", 3, 17, 1], 3]); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(7); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.value.tree).eq( + 7, + ); + expect( + stateVariables["/numbersAsMacros2"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacro"].stateValues.value.tree, + ).eq(7); + expect( + stateVariables["/withNumberMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMathMacro"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .value.tree, + ).eqls(["/", ["+", 3, 17, 1], 3]); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(7); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacro"].stateValues.value.tree, + ).eqls(["/", ["+", ["/", 6, 2], 17, 1], 3]); + expect( + stateVariables["/withNumericMathMacro"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/withNumericMathMacro"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues.value + .tree, + ).eq(7); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .value.tree, + ).eq(7); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "/", + ["+", "x", "x", "y", "x", "y", "z"], + 3, + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsAsString"].stateValues.value.tree).eqls([ + "/", + ["+", "x", "x", "y", "x", "y", "z"], + 3, + ]); + expect( + stateVariables["/varsAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/varsAsStringSimplify"].stateValues.value.tree, + ).eqls(["/", ["+", ["*", 3, "x"], ["*", 2, "y"], "z"], 3]); + expect(stateVariables["/varsAsStringSimplify"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.isNumber, + ).eq(false); + }); + + it("mean as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 3 + 17 + 5-4 + + mean(3,17,5-4) + mean(3,17,5-4) + mean(3 17 5-4) + mean(3 17 5-4) + + mean(3,17,5-4) + + + mean(3,17,5-4) + + + mean(3175-4) + + + mean(3175-4) + + + mean($a,$b,$c) + + + mean($a,$b,$c) + + + mean($a$b$c) + + + mean($a$b$c) + + + mean($nums) + + + mean($nums) + + + mean($nums, $a, $b, $c) + + + mean($nums, $a, $b, $c) + + + mean($a, $b, $c, $nums) + + + mean($a, $b, $c, $nums) + + + mean($a, $b, $nums, $c) + + + mean($a, $b, $nums, $c) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "mean", + ["tuple", 3, 17, ["+", 5, -4]], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(7); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numberStringProduct"].stateValues.value.tree, + ).eqls(["apply", "mean", ["+", ["*", 3, 17, 5], -4]]); + expect(stateVariables["/numberStringProduct"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.value + .tree, + ).eq(251); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "mean", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsCommas"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(7); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numberComponentsProduct"].stateValues.value.tree, + ).eqls(["apply", "mean", ["*", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsProduct"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "mean", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(7); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/macrosProduct"].stateValues.value.tree).eqls([ + "apply", + "mean", + ["*", 3, 17, 1], + ]); + expect(stateVariables["/macrosProduct"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosProductSimplify"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/macrosProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "mean", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq(7); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + + expect(stateVariables["/groupPlus"].stateValues.value.tree).eqls([ + "apply", + "mean", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlusSimplify"].stateValues.value.tree).eq( + 7, + ); + expect(stateVariables["/groupPlusSimplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus2"].stateValues.value.tree).eqls([ + "apply", + "mean", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus2Simplify"].stateValues.value.tree).eq( + 7, + ); + expect(stateVariables["/groupPlus2Simplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus3"].stateValues.value.tree).eqls([ + "apply", + "mean", + ["tuple", 3, 17, 3, 17, 1, 1], + ]); + expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus3Simplify"].stateValues.value.tree).eq( + 7, + ); + expect(stateVariables["/groupPlus3Simplify"].stateValues.isNumber).eq( + true, + ); + }); + + it("mean additional cases", async () => { + let core = await createTestCore({ + doenetML: ` +

Mean of first primes: 2 3 5 7

+

Copying that mean: $meanPrime{name="meanPrimeb"}

+ $pPrime{name="pPrimeb"} + +

Mean of numbers from 1 to 100:

+

Copying that mean: $mean100{name="mean100b"}

+ $p100{name="p100b"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/meanPrime"].stateValues.value.tree).eq(4.25); + expect(stateVariables["/meanPrimeb"].stateValues.value.tree).eq(4.25); + expect( + stateVariables[ + stateVariables["/pPrimeb"].activeChildren[1].componentName + ].stateValues.value.tree, + ).eq(4.25); + expect(stateVariables["/mean100"].stateValues.value.tree).eq(50.5); + expect(stateVariables["/mean100b"].stateValues.value.tree).eq(50.5); + expect( + stateVariables[ + stateVariables["/p100b"].activeChildren[1].componentName + ].stateValues.value.tree, + ).eq(50.5); + }); + + it("median", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 1 4 5 10000 + 1 4 5 x+1 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(3); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + + expect(stateVariables["/sugared"].stateValues.value.tree).eq(4.5); + expect(stateVariables["/sugared"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/sugared"].stateValues.isNumber).eq(true); + + expect(stateVariables["/noSymbolic"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/noSymbolic"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/noSymbolic"].stateValues.isNumber).eq(false); + }); + + // TODO: skipping most checks of ugly expressions for now + it("variance", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 6/2175-4 + 6/2175-4 + 6/2175-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let theVariance = me.math.variance([3, 17, 1]); + let theVarianceString = theVariance.toString(); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq( + theVariance, + ); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + // expect(stateVariables['/numbersForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(theVariance); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(theVariance); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/numbersWithNumberMathForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(theVariance); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/numbersWithNumericMath'].stateValues.value.tree).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(theVariance); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(theVariance); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberVariance"].stateValues.value.tree).eq( + me.math.variance([3, me.math.variance([17, 1])]), + ); + expect( + stateVariables["/withNumberVariance"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberVariance"].stateValues.isNumber).eq( + true, + ); + // expect(stateVariables['/vars'].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + // expect(stateVariables['/varsSimplify'].stateValues.value.tree).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq( + theVariance, + ); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + // expect(stateVariables["/varsb"].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("variance with sugar", async () => { + let core = await createTestCore({ + doenetML: ` + 3 + 17 + 5-4 + 3 + 6/2 + 3175-4 + 3 17 1 + 3 17 1 + 3 17 1 + 6/2 17 5-4 + 6/2 17 5-4 + 6/2 17 5-4 + $a$b$c + $a$b$c + $a$b$c + $a $b $c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + xx+yx+y+z + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + `, + }); + + let theVariance = me.math.variance([3, 17, 1]); + let theVarianceString = theVariance.toString(); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq( + theVariance, + ); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.value.tree).eq( + theVariance, + ); + expect( + stateVariables["/numbersAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.isNumber).eq( + true, + ); + // expect(stateVariables['/numbersAsStringForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(theVariance); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + // expect(stateVariables['/numericAsString'].stateValues.value.tree).eqls(['/', ['+', ['/', 6, 2], 17, 5, -4], 3]); + expect( + stateVariables["/numericAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/numericAsString"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.value.tree, + ).eq(theVariance); + expect( + stateVariables["/numericAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.value + .tree, + ).eq(theVariance); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.value.tree).eq( + theVariance, + ); + expect( + stateVariables["/numbersAsMacros"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.isNumber).eq( + true, + ); + // expect(stateVariables['/numbersAsMacrosForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(theVariance); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.value.tree).eq( + theVariance, + ); + expect( + stateVariables["/numbersAsMacros2"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacro"].stateValues.value.tree, + ).eq(theVariance); + expect( + stateVariables["/withNumberMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMathMacro"].stateValues.isNumber).eq( + true, + ); + // expect(stateVariables['/withNumberMathMacroForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(theVariance); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/withNumericMathMacro'].stateValues.value.tree).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); + expect( + stateVariables["/withNumericMathMacro"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/withNumericMathMacro"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues.value + .tree, + ).eq(theVariance); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .value.tree, + ).eq(theVariance); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumber, + ).eq(true); + // expect(stateVariables['/vars'].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + // expect(stateVariables['/varsAsString'].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect( + stateVariables["/varsAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + // expect(stateVariables['/varsAsStringSimplify'].stateValues.value.tree).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); + expect(stateVariables["/varsAsStringSimplify"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.isNumber, + ).eq(false); + }); + + it("variance as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 3 + 17 + 5-4 + + variance(3,17,5-4) + variance(3,17,5-4) + variance(3 17 5-4) + variance(3 17 5-4) + + variance(3,17,5-4) + + + variance(3,17,5-4) + + + variance(3175-4) + + + variance(3175-4) + + + variance($a,$b,$c) + + + variance($a,$b,$c) + + + variance($a$b$c) + + + variance($a$b$c) + + + variance($nums) + + + variance($nums) + + + variance($nums, $a, $b, 13) + + + variance($nums, $a, $b, 13) + + + variance($a, $b, 13, $nums) + + + variance($a, $b, 13, $nums) + + + variance($a, $b, $nums, 13) + + + variance($a, $b, $nums, 13) + + `, + }); + + let theVariance = me.math.variance([3, 17, 1]); + let theVariance2 = me.math.variance([3, 17, 1, 3, 17, 13]); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "variance", + ["tuple", 3, 17, ["+", 5, -4]], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(theVariance); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numberStringProduct"].stateValues.value.tree, + ).eqls(["apply", "variance", ["+", ["*", 3, 17, 5], -4]]); + expect(stateVariables["/numberStringProduct"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.value + .tree, + ).eq(0); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "variance", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsCommas"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(theVariance); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numberComponentsProduct"].stateValues.value.tree, + ).eqls(["apply", "variance", ["*", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsProduct"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues.value + .tree, + ).eq(0); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "variance", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(theVariance); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/macrosProduct"].stateValues.value.tree).eqls([ + "apply", + "variance", + ["*", 3, 17, 1], + ]); + expect(stateVariables["/macrosProduct"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosProductSimplify"].stateValues.value.tree, + ).eq(0); + expect( + stateVariables["/macrosProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "variance", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq( + theVariance, + ); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + + expect(stateVariables["/groupPlus"].stateValues.value.tree).eqls([ + "apply", + "variance", + ["tuple", 3, 17, 1, 3, 17, 13], + ]); + expect(stateVariables["/groupPlus"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlusSimplify"].stateValues.value.tree).eq( + theVariance2, + ); + expect(stateVariables["/groupPlusSimplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus2"].stateValues.value.tree).eqls([ + "apply", + "variance", + ["tuple", 3, 17, 13, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus2Simplify"].stateValues.value.tree).eq( + theVariance2, + ); + expect(stateVariables["/groupPlus2Simplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus3"].stateValues.value.tree).eqls([ + "apply", + "variance", + ["tuple", 3, 17, 3, 17, 1, 13], + ]); + expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus3Simplify"].stateValues.value.tree).eq( + theVariance2, + ); + expect(stateVariables["/groupPlus3Simplify"].stateValues.isNumber).eq( + true, + ); + }); + + it("variance additional cases", async () => { + let core = await createTestCore({ + doenetML: ` +

Variance of first primes: 2 3 5 7

+

Copying that variance: $variancePrime{name="variancePrimeb"}

+ $pPrime{name="pPrimeb"} + +

Variance of numbers from 1 to 100:

+

Copying that variance: $variance100{name="variance100b"}

+ $p100{name="p100b"} + `, + }); + + let variancePrimes = me.math.variance(2, 3, 5, 7); + let variance100 = me.math.variance( + Array.from({ length: 100 }, (_, i) => i + 1), + ); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/variancePrime"].stateValues.value.tree).closeTo( + variancePrimes, + 1e-12, + ); + expect( + stateVariables["/variancePrimeb"].stateValues.value.tree, + ).closeTo(variancePrimes, 1e-12); + expect( + stateVariables[ + stateVariables["/pPrimeb"].activeChildren[1].componentName + ].stateValues.value.tree, + ).closeTo(variancePrimes, 1e-12); + expect(stateVariables["/variance100"].stateValues.value.tree).closeTo( + variance100, + 1e-12, + ); + expect(stateVariables["/variance100b"].stateValues.value.tree).closeTo( + variance100, + 1e-12, + ); + expect( + stateVariables[ + stateVariables["/p100b"].activeChildren[1].componentName + ].stateValues.value.tree, + ).closeTo(variance100, 1e-12); + }); + + // TODO: skipping most checks of ugly expressions for now + it("population variance", async () => { + let core = await createTestCore({ + doenetML: ` + 4165-4 + 4165-4 + 4165-4 + 4165-4 + 4165-4 + 4165-4 + 8/2165-4 + 8/2165-4 + 8/2165-4 + 4175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let theVariance = me.math.variance([4, 16, 1], "uncorrected"); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq( + theVariance, + ); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + // expect(stateVariables['/numbersForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(theVariance); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(theVariance); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/numbersWithNumberMathForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(theVariance); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/numbersWithNumericMath'].stateValues.value.tree).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(theVariance); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(theVariance); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberVariance"].stateValues.value.tree).eq( + me.math.variance( + [4, me.math.variance([17, 1], "uncorrected")], + "uncorrected", + ), + ); + expect( + stateVariables["/withNumberVariance"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberVariance"].stateValues.isNumber).eq( + true, + ); + // expect(stateVariables['/vars'].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + // expect(stateVariables['/varsSimplify'].stateValues.value.tree).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq( + theVariance, + ); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + // expect(stateVariables["/varsb"].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("population variance additional cases", async () => { + let core = await createTestCore({ + doenetML: ` +

Variance of first primes: 2 3 5 7

+

Copying that variance: $variancePrime{name="variancePrimeb"}

+ $pPrime{name="pPrimeb"} + +

Variance of numbers from 1 to 100:

+

Copying that variance: $variance100{name="variance100b"}

+ $p100{name="p100b"} + `, + }); + + let variancePrimes = me.math.variance([2, 3, 5, 7], "uncorrected"); + let variance100 = me.math.variance( + Array.from({ length: 100 }, (_, i) => i + 1), + "uncorrected", + ); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/variancePrime"].stateValues.value.tree).closeTo( + variancePrimes, + 1e-12, + ); + expect( + stateVariables["/variancePrimeb"].stateValues.value.tree, + ).closeTo(variancePrimes, 1e-12); + expect( + stateVariables[ + stateVariables["/pPrimeb"].activeChildren[1].componentName + ].stateValues.value.tree, + ).closeTo(variancePrimes, 1e-12); + expect(stateVariables["/variance100"].stateValues.value.tree).closeTo( + variance100, + 1e-12, + ); + expect(stateVariables["/variance100b"].stateValues.value.tree).closeTo( + variance100, + 1e-12, + ); + expect( + stateVariables[ + stateVariables["/p100b"].activeChildren[1].componentName + ].stateValues.value.tree, + ).closeTo(variance100, 1e-12); + }); + + // TODO: skipping most checks of ugly expressions for now + it("standard deviation", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 6/2175-4 + 6/2175-4 + 6/2175-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let theStandardDeviation = me.math.std([3, 17, 1]); + + expect(stateVariables["/numbers"].stateValues.value.tree).closeTo( + theStandardDeviation, + 1e-12, + ); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + // expect(stateVariables['/numbersForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eqls(["apply", "sqrt", 76]); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).closeTo(theStandardDeviation, 1e-16); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/numbersWithNumberMathForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eqls(["apply", "sqrt", 76]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(false); + // expect(stateVariables['/numbersWithNumericMath'].stateValues.value.tree).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eqls(["apply", "sqrt", 76]); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).closeTo(theStandardDeviation, 1e-12); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumberStandardDeviation"].stateValues.value + .tree, + ).closeTo(me.math.std([3, me.math.std([17, 1])]), 1e-12); + expect( + stateVariables["/withNumberStandardDeviation"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumberStandardDeviation"].stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/vars'].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + // expect(stateVariables['/varsSimplify'].stateValues.value.tree).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).closeTo( + theStandardDeviation, + 1e-12, + ); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + // expect(stateVariables["/varsb"].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("standard deviation as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 13 + 25 + 5-4 + + std(13,25,5-4) + std(13,25,5-4) + std(13 25 5-4) + std(13 25 5-4) + + std(13,25,5-4) + + + std(13,25,5-4) + + + std(13255-4) + + + std(13255-4) + + + std($a,$b,$c) + + + std($a,$b,$c) + + + std($a$b$c) + + + std($a$b$c) + + + std($nums) + + + std($nums) + + `, + }); + + let theStd = me.math.std([13, 25, 1]); + let theStdString = theStd.toString(); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "std", + ["tuple", 13, 25, ["+", 5, -4]], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(theStd); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numberStringProduct"].stateValues.value.tree, + ).eqls(["apply", "std", ["+", ["*", 13, 25, 5], -4]]); + expect(stateVariables["/numberStringProduct"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.value + .tree, + ).eq(0); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "std", ["tuple", 13, 25, 1]]); + expect( + stateVariables["/numberComponentsCommas"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(theStd); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numberComponentsProduct"].stateValues.value.tree, + ).eqls(["apply", "std", ["*", 13, 25, 1]]); + expect( + stateVariables["/numberComponentsProduct"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues.value + .tree, + ).eq(0); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "std", + ["tuple", 13, 25, 1], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(theStd); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/macrosProduct"].stateValues.value.tree).eqls([ + "apply", + "std", + ["*", 13, 25, 1], + ]); + expect(stateVariables["/macrosProduct"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosProductSimplify"].stateValues.value.tree, + ).eq(0); + expect( + stateVariables["/macrosProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "std", + ["tuple", 13, 25, 1], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq( + theStd, + ); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + }); + + it("standard deviation additional cases", async () => { + let core = await createTestCore({ + doenetML: ` +

Standard deviation of first primes: 2 3 5 7

+

Copying that standard deviation: $standarddeviationPrime{name="standarddeviationPrimeb"}

+ $pPrime{name="pPrimeb"} + +

Standard deviation of numbers from 1 to 100:

+

Copying that standard deviation: $standarddeviation100{name="standarddeviation100b"}

+ $p100{name="p100b"} + `, + }); + + let stdPrimes = me.math.std(2, 3, 5, 7); + let std100 = me.math.std(Array.from({ length: 100 }, (_, i) => i + 1)); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/standarddeviationPrime"].stateValues.value.tree, + ).closeTo(stdPrimes, 1e-12); + expect( + stateVariables["/standarddeviationPrimeb"].stateValues.value.tree, + ).closeTo(stdPrimes, 1e-12); + expect( + stateVariables[ + stateVariables["/pPrimeb"].activeChildren[1].componentName + ].stateValues.value.tree, + ).closeTo(stdPrimes, 1e-12); + expect( + stateVariables["/standarddeviation100"].stateValues.value.tree, + ).closeTo(std100, 1e-12); + expect( + stateVariables["/standarddeviation100b"].stateValues.value.tree, + ).closeTo(std100, 1e-12); + expect( + stateVariables[ + stateVariables["/p100b"].activeChildren[1].componentName + ].stateValues.value.tree, + ).closeTo(std100, 1e-12); + }); + + // TODO: skipping most checks of ugly expressions for now + it("population standard deviation", async () => { + let core = await createTestCore({ + doenetML: ` + 4165-4 + 4165-4 + 4165-4 + 4165-4 + 4165-4 + 4165-4 + 8/2165-4 + 8/2165-4 + 8/2165-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let theStandardDeviation = me.math.std([4, 16, 1], "uncorrected"); + + expect(stateVariables["/numbers"].stateValues.value.tree).closeTo( + theStandardDeviation, + 1e-12, + ); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + // expect(stateVariables['/numbersForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eqls(["apply", "sqrt", 42]); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).closeTo(theStandardDeviation, 1e-16); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/numbersWithNumberMathForceSymbolic'].stateValues.value.tree).eqls(['/', ['+', 3, 17, 1], 3]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eqls(["apply", "sqrt", 42]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(false); + // expect(stateVariables['/numbersWithNumericMath'].stateValues.value.tree).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eqls(["apply", "sqrt", 42]); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).closeTo(theStandardDeviation, 1e-12); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumberStandardDeviation"].stateValues.value + .tree, + ).closeTo( + me.math.std( + [3, me.math.std([17, 1], "uncorrected")], + "uncorrected", + ), + 1e-12, + ); + expect( + stateVariables["/withNumberStandardDeviation"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumberStandardDeviation"].stateValues.isNumber, + ).eq(true); + // expect(stateVariables['/vars'].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + // expect(stateVariables['/varsSimplify'].stateValues.value.tree).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).closeTo( + theStandardDeviation, + 1e-12, + ); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + // expect(stateVariables["/varsb"].stateValues.value.tree).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("population standard deviation additional cases", async () => { + let core = await createTestCore({ + doenetML: ` +

Standard deviation of first primes: 2 3 5 7

+

Copying that standard deviation: $standarddeviationPrime{name="standarddeviationPrimeb"}

+ $pPrime{name="pPrimeb"} + +

Standard deviation of numbers from 1 to 100:

+

Copying that standard deviation: $standarddeviation100{name="standarddeviation100b"}

+ $p100{name="p100b"} + `, + }); + + let stdPrimes = me.math.std([2, 3, 5, 7], "uncorrected"); + let std100 = me.math.std( + Array.from({ length: 100 }, (_, i) => i + 1), + "uncorrected", + ); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/standarddeviationPrime"].stateValues.value.tree, + ).closeTo(stdPrimes, 1e-12); + expect( + stateVariables["/standarddeviationPrimeb"].stateValues.value.tree, + ).closeTo(stdPrimes, 1e-12); + expect( + stateVariables[ + stateVariables["/pPrimeb"].activeChildren[1].componentName + ].stateValues.value.tree, + ).closeTo(stdPrimes, 1e-12); + expect( + stateVariables["/standarddeviation100"].stateValues.value.tree, + ).closeTo(std100, 1e-12); + expect( + stateVariables["/standarddeviation100b"].stateValues.value.tree, + ).closeTo(std100, 1e-12); + expect( + stateVariables[ + stateVariables["/p100b"].activeChildren[1].componentName + ].stateValues.value.tree, + ).closeTo(std100, 1e-12); + }); + + it("count", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 6/2175-4 + 6/2175-4 + 6/2175-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(3); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(3); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eq(3); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(3); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(3); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberCount"].stateValues.value.tree).eq(2); + expect( + stateVariables["/withNumberCount"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberCount"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/vars"].stateValues.value.tree).eq(3); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(true); + expect(stateVariables["/vars"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsSimplify"].stateValues.value.tree).eq(3); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.value.tree).eq( + 3, + ); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(3); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsb"].stateValues.value.tree).eq(3); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq(true); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(true); + }); + + it("count with sugar", async () => { + let core = await createTestCore({ + doenetML: ` + 3 + 17 + 5-4 + 3 + 6/2 + 3175-4 + 3 17 1 + 3 17 1 + 3 17 1 + 6/2 17 5-4 + 6/2 17 5-4 + 6/2 17 5-4 + $a$b$c + $a$b$c + $a$b$c + $a $b $c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + xx+yx+y+z + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(3); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.value.tree).eq(3); + expect( + stateVariables["/numbersAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues.value + .tree, + ).eq(3); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(3); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numericAsString"].stateValues.value.tree).eq(3); + expect( + stateVariables["/numericAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numericAsString"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/numericAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.value + .tree, + ).eq(3); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.value.tree).eq(3); + expect( + stateVariables["/numbersAsMacros"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues.value + .tree, + ).eq(3); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(3); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.value.tree).eq( + 3, + ); + expect( + stateVariables["/numbersAsMacros2"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacro"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/withNumberMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMathMacro"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .value.tree, + ).eq(3); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacro"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/withNumericMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumericMathMacro"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues.value + .tree, + ).eq(3); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .value.tree, + ).eq(3); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eq(3); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(true); + expect(stateVariables["/vars"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsAsString"].stateValues.value.tree).eq(3); + expect( + stateVariables["/varsAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsAsString"].stateValues.isNumber).eq(true); + expect( + stateVariables["/varsAsStringSimplify"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/varsAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/varsAsStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + }); + + it("count as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 3 + 17 + 5-4 + + count(3,17,5-4) + count(3,17,5-4) + count([3,17,5-4]) + count([3,17,5-4]) + count(3 17 5-4) + count(3 17 5-4) + + count(3,17,5-4) + + + count(3,17,5-4) + + + count(3175-4) + + + count(3175-4) + + + count($a,$b,$c) + + + count($a,$b,$c) + + + count($a$b$c) + + + count($a$b$c) + + + count($nums) + + + count($nums) + + + count($nums, $a, $b, $c) + + + count($nums, $a, $b, $c) + + + count($a, $b, $c, $nums) + + + count($a, $b, $c, $nums) + + + count($a, $b, $nums, $c) + + + count($a, $b, $nums, $c) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "count", + ["tuple", 3, 17, ["+", 5, -4]], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(3); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numberStringArray"].stateValues.value.tree, + ).eqls(["apply", "count", ["array", 3, 17, ["+", 5, -4]]]); + expect(stateVariables["/numberStringArray"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringArraySimplify"].stateValues.value.tree, + ).eq(3); + expect( + stateVariables["/numberStringArraySimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numberStringProduct"].stateValues.value.tree, + ).eqls(["apply", "count", ["+", ["*", 3, 17, 5], -4]]); + expect(stateVariables["/numberStringProduct"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.value + .tree, + ).eq(1); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "count", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsCommas"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(3); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numberComponentsProduct"].stateValues.value.tree, + ).eqls(["apply", "count", ["*", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsProduct"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues.value + .tree, + ).eq(1); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "count", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(3); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/macrosProduct"].stateValues.value.tree).eqls([ + "apply", + "count", + ["*", 3, 17, 1], + ]); + expect(stateVariables["/macrosProduct"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosProductSimplify"].stateValues.value.tree, + ).eq(1); + expect( + stateVariables["/macrosProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "count", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq(3); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + + expect(stateVariables["/groupPlus"].stateValues.value.tree).eqls([ + "apply", + "count", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlusSimplify"].stateValues.value.tree).eq( + 6, + ); + expect(stateVariables["/groupPlusSimplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus2"].stateValues.value.tree).eqls([ + "apply", + "count", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus2Simplify"].stateValues.value.tree).eq( + 6, + ); + expect(stateVariables["/groupPlus2Simplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus3"].stateValues.value.tree).eqls([ + "apply", + "count", + ["tuple", 3, 17, 3, 17, 1, 1], + ]); + expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus3Simplify"].stateValues.value.tree).eq( + 6, + ); + expect(stateVariables["/groupPlus3Simplify"].stateValues.isNumber).eq( + true, + ); + }); + + it("count additional cases", async () => { + let core = await createTestCore({ + doenetML: ` +

Count of first primes: 2 3 5 7

+

Copying that count: $countPrime{name="countPrimeb"}

+ $pPrime{name="pPrimeb"} + +

Count of numbers from 1 to 100:

+

Copying that count: $count100{name="count100b"}

+ $p100{name="p100b"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/countPrime"].stateValues.value.tree).eq(4); + expect(stateVariables["/countPrimeb"].stateValues.value.tree).eq(4); + expect( + stateVariables[ + stateVariables["/pPrimeb"].activeChildren[1].componentName + ].stateValues.value.tree, + ).eq(4); + expect(stateVariables["/count100"].stateValues.value.tree).eq(100); + expect(stateVariables["/count100b"].stateValues.value.tree).eq(100); + expect( + stateVariables[ + stateVariables["/p100b"].activeChildren[1].componentName + ].stateValues.value.tree, + ).eq(100); + }); + + it("min", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 6/2175-4 + 6/2175-4 + 6/2175-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(1); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(1); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(1); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(1); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eqls(["apply", "min", ["tuple", ["/", 6, 2], 17, 1]]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(1); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(1); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberMin"].stateValues.value.tree).eq(1); + expect( + stateVariables["/withNumberMin"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMin"].stateValues.isNumber).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(1); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsb"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("min with sugar", async () => { + let core = await createTestCore({ + doenetML: ` + 3 + 17 + 5-4 + 3 + 6/2 + 3175-4 + 3 17 1 + 3 17 1 + 3 17 1 + 6/2 17 5-4 + 6/2 17 5-4 + 6/2 17 5-4 + $a$b$c + $a$b$c + $a$b$c + $a $b $c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + xx+yx+y+z + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(1); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.value.tree).eq(1); + expect( + stateVariables["/numbersAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues.value + .tree, + ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(1); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numericAsString"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", ["/", 6, 2], 17, ["+", 5, -4]], + ]); + expect( + stateVariables["/numericAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/numericAsString"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.value.tree, + ).eq(1); + expect( + stateVariables["/numericAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.value + .tree, + ).eq(1); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.value.tree).eq(1); + expect( + stateVariables["/numbersAsMacros"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues.value + .tree, + ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(1); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.value.tree).eq( + 1, + ); + expect( + stateVariables["/numbersAsMacros2"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacro"].stateValues.value.tree, + ).eq(1); + expect( + stateVariables["/withNumberMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMathMacro"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .value.tree, + ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(1); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacro"].stateValues.value.tree, + ).eqls(["apply", "min", ["tuple", ["/", 6, 2], 17, 1]]); + expect( + stateVariables["/withNumericMathMacro"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/withNumericMathMacro"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues.value + .tree, + ).eq(1); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .value.tree, + ).eq(1); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsAsString"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect( + stateVariables["/varsAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsAsStringSimplify"].stateValues.value.tree, + ).eqls([ + "apply", + "min", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect( + stateVariables["/varsAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsStringSimplify"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.isNumber, + ).eq(false); + }); + + it("min as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 3 + 17 + 5-4 + + min(3,17,5-4) + min(3,17,5-4) + min(3 17 5-4) + min(3 17 5-4) + + min(3,17,5-4) + + + min(3,17,5-4) + + + min(3175-4) + + + min(3175-4) + + + min($a,$b,$c) + + + min($a,$b,$c) + + + min($a$b$c) + + + min($a$b$c) + + + min($nums) + + + min($nums) + + + min($nums, $a, $b, $c) + + + min($nums, $a, $b, $c) + + + min($a, $b, $c, $nums) + + + min($a, $b, $c, $nums) + + + min($a, $b, $nums, $c) + + + min($a, $b, $nums, $c) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", 3, 17, ["+", 5, -4]], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(1); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numberStringProduct"].stateValues.value.tree, + ).eqls(["apply", "min", ["+", ["*", 3, 17, 5], -4]]); + expect(stateVariables["/numberStringProduct"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.value + .tree, + ).eq(251); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsCommas"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(1); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numberComponentsProduct"].stateValues.value.tree, + ).eqls(["apply", "min", ["*", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsProduct"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(1); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/macrosProduct"].stateValues.value.tree).eqls([ + "apply", + "min", + ["*", 3, 17, 1], + ]); + expect(stateVariables["/macrosProduct"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosProductSimplify"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/macrosProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq(1); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + + expect(stateVariables["/groupPlus"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlusSimplify"].stateValues.value.tree).eq( + 1, + ); + expect(stateVariables["/groupPlusSimplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus2"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus2Simplify"].stateValues.value.tree).eq( + 1, + ); + expect(stateVariables["/groupPlus2Simplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus3"].stateValues.value.tree).eqls([ + "apply", + "min", + ["tuple", 3, 17, 3, 17, 1, 1], + ]); + expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus3Simplify"].stateValues.value.tree).eq( + 1, + ); + expect(stateVariables["/groupPlus3Simplify"].stateValues.isNumber).eq( + true, + ); + }); + + it("max", async () => { + let core = await createTestCore({ + doenetML: ` + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 3175-4 + 6/2175-4 + 6/2175-4 + 6/2175-4 + 3175-4 + xx+yx+y+z + xx+yx+y+z + xx+yx+y+z + $numbers{name="numbersb"} + $vars{name="varsb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(17); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(17); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(17); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(17); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eqls(["apply", "max", ["tuple", ["/", 6, 2], 17, 1]]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(17); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(17); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberMax"].stateValues.value.tree).eq(17); + expect( + stateVariables["/withNumberMax"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMax"].stateValues.isNumber).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect( + stateVariables["/varsSimplify"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsForcedNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsForcedNumeric"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/varsForcedNumeric"].stateValues.isNumber).eq( + false, + ); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(17); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + expect(stateVariables["/varsb"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect(stateVariables["/varsb"].stateValues.isNumericOperator).eq( + false, + ); + expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); + }); + + it("max with sugar", async () => { + let core = await createTestCore({ + doenetML: ` + 3 + 17 + 5-4 + 3 + 6/2 + 3175-4 + 3 17 1 + 3 17 1 + 3 17 1 + 6/2 17 5-4 + 6/2 17 5-4 + 6/2 17 5-4 + $a$b$c + $a$b$c + $a$b$c + $a $b $c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumberMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + $aNumericMath$b$c + xx+yx+y+z + x x+y x+y+z + x x+y x+y+z + x x+y x+y+z + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(17); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.value.tree).eq( + 17, + ); + expect( + stateVariables["/numbersAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues.value + .tree, + ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(17); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numericAsString"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", ["/", 6, 2], 17, ["+", 5, -4]], + ]); + expect( + stateVariables["/numericAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/numericAsString"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.value.tree, + ).eq(17); + expect( + stateVariables["/numericAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.value + .tree, + ).eq(17); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.value.tree).eq( + 17, + ); + expect( + stateVariables["/numbersAsMacros"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues.value + .tree, + ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(17); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.value.tree).eq( + 17, + ); + expect( + stateVariables["/numbersAsMacros2"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacro"].stateValues.value.tree, + ).eq(17); + expect( + stateVariables["/withNumberMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMathMacro"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .value.tree, + ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(17); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacro"].stateValues.value.tree, + ).eqls(["apply", "max", ["tuple", ["/", 6, 2], 17, 1]]); + expect( + stateVariables["/withNumericMathMacro"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/withNumericMathMacro"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues.value + .tree, + ).eq(17); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .value.tree, + ).eq(17); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/vars"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect(stateVariables["/vars"].stateValues.isNumericOperator).eq(false); + expect(stateVariables["/vars"].stateValues.isNumber).eq(false); + expect(stateVariables["/varsAsString"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect( + stateVariables["/varsAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/varsAsStringSimplify"].stateValues.value.tree, + ).eqls([ + "apply", + "max", + ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], + ]); + expect( + stateVariables["/varsAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/varsAsStringSimplify"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/varsAsStringForceNumeric"].stateValues.isNumber, + ).eq(false); + }); + + it("max as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 3 + 17 + 5-4 + + max(3,17,5-4) + max(3,17,5-4) + max(3 17 5-4) + max(3 17 5-4) + + max(3,17,5-4) + + + max(3,17,5-4) + + + max(3175-4) + + + max(3175-4) + + + max($a,$b,$c) + + + max($a,$b,$c) + + + max($a$b$c) + + + max($a$b$c) + + + max($nums) + + + max($nums) + + + max($nums, $a, $b, $c) + + + max($nums, $a, $b, $c) + + + max($a, $b, $c, $nums) + + + max($a, $b, $c, $nums) + + + max($a, $b, $nums, $c) + + + max($a, $b, $nums, $c) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", 3, 17, ["+", 5, -4]], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(17); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numberStringProduct"].stateValues.value.tree, + ).eqls(["apply", "max", ["+", ["*", 3, 17, 5], -4]]); + expect(stateVariables["/numberStringProduct"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.value + .tree, + ).eq(251); + expect( + stateVariables["/numberStringProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsCommas"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(17); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numberComponentsProduct"].stateValues.value.tree, + ).eqls(["apply", "max", ["*", 3, 17, 1]]); + expect( + stateVariables["/numberComponentsProduct"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues.value + .tree, + ).eq(51); + expect( + stateVariables["/numberComponentsProductSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(17); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + expect(stateVariables["/macrosProduct"].stateValues.value.tree).eqls([ + "apply", + "max", + ["*", 3, 17, 1], + ]); + expect(stateVariables["/macrosProduct"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosProductSimplify"].stateValues.value.tree, + ).eq(51); + expect( + stateVariables["/macrosProductSimplify"].stateValues.isNumber, + ).eq(true); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", 3, 17, 1], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq(17); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + + expect(stateVariables["/groupPlus"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlusSimplify"].stateValues.value.tree).eq( + 17, + ); + expect(stateVariables["/groupPlusSimplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus2"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", 3, 17, 1, 3, 17, 1], + ]); + expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus2Simplify"].stateValues.value.tree).eq( + 17, + ); + expect(stateVariables["/groupPlus2Simplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/groupPlus3"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", 3, 17, 3, 17, 1, 1], + ]); + expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupPlus3Simplify"].stateValues.value.tree).eq( + 17, + ); + expect(stateVariables["/groupPlus3Simplify"].stateValues.isNumber).eq( + true, + ); + }); + + it("max can be invertible", async () => { + let core = await createTestCore({ + doenetML: ` + 36 + 36 + 36 + 36 + + 36 + 36 + 36 + 36 + + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers00"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers01"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers10"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers11"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths00"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths01"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths10"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths11"].stateValues.value.tree).eq(6); + + await updateMathInputValue({ + componentName: "/minumbers00", + latex: "9", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers01", + latex: "9", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers10", + latex: "9", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers11", + latex: "9", + core, + }); + + await updateMathInputValue({ + componentName: "/mimaths00", + latex: "9", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths01", + latex: "9", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths10", + latex: "9", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths11", + latex: "9", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers00"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers01"].stateValues.value.tree).eq(9); + expect(stateVariables["/numbers10"].stateValues.value.tree).eq(9); + expect(stateVariables["/numbers11"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths00"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths01"].stateValues.value.tree).eq(9); + expect(stateVariables["/maths10"].stateValues.value.tree).eq(9); + expect(stateVariables["/maths11"].stateValues.value.tree).eq(6); + + await updateMathInputValue({ + componentName: "/minumbers00", + latex: "5", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers01", + latex: "5", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers10", + latex: "5", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers11", + latex: "5", + core, + }); + + await updateMathInputValue({ + componentName: "/mimaths00", + latex: "5", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths01", + latex: "5", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths10", + latex: "5", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths11", + latex: "5", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers00"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers01"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers10"].stateValues.value.tree).eq(5); + expect(stateVariables["/numbers11"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths00"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths01"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths10"].stateValues.value.tree).eq(5); + expect(stateVariables["/maths11"].stateValues.value.tree).eq(6); + + await updateMathInputValue({ + componentName: "/minumbers00", + latex: "2", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers01", + latex: "2", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers10", + latex: "2", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers11", + latex: "2", + core, + }); + + await updateMathInputValue({ + componentName: "/mimaths00", + latex: "2", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths01", + latex: "2", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths10", + latex: "2", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths11", + latex: "2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers00"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers01"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers10"].stateValues.value.tree).eq(3); + expect(stateVariables["/numbers11"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths00"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths01"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths10"].stateValues.value.tree).eq(3); + expect(stateVariables["/maths11"].stateValues.value.tree).eq(6); + + await updateMathInputValue({ + componentName: "/minumbers00", + latex: "x", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers01", + latex: "x", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers10", + latex: "x", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers11", + latex: "x", + core, + }); + + await updateMathInputValue({ + componentName: "/mimaths00", + latex: "x", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths01", + latex: "x", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths10", + latex: "x", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths11", + latex: "x", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers00"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers01"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/numbers10"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/numbers11"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths00"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths01"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", "x", 6], + ]); + expect(stateVariables["/maths10"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", 3, "x"], + ]); + expect(stateVariables["/maths11"].stateValues.value.tree).eq(6); + + await updateMathInputValue({ + componentName: "/minumbers00", + latex: "y", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers01", + latex: "y", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers10", + latex: "y", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers11", + latex: "y", + core, + }); + + await updateMathInputValue({ + componentName: "/mimaths00", + latex: "y", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths01", + latex: "y", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths10", + latex: "y", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths11", + latex: "y", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers00"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers01"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/numbers10"].stateValues.value.tree).eqls(NaN); + expect(stateVariables["/numbers11"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths00"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths01"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", "y", 6], + ]); + expect(stateVariables["/maths10"].stateValues.value.tree).eqls([ + "apply", + "max", + ["tuple", 3, "y"], + ]); + expect(stateVariables["/maths11"].stateValues.value.tree).eq(6); + + await updateMathInputValue({ + componentName: "/minumbers00", + latex: "7", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers01", + latex: "7", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers10", + latex: "7", + core, + }); + await updateMathInputValue({ + componentName: "/minumbers11", + latex: "7", + core, + }); + + await updateMathInputValue({ + componentName: "/mimaths00", + latex: "7", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths01", + latex: "7", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths10", + latex: "7", + core, + }); + await updateMathInputValue({ + componentName: "/mimaths11", + latex: "7", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers00"].stateValues.value.tree).eq(6); + expect(stateVariables["/numbers01"].stateValues.value.tree).eq(7); + expect(stateVariables["/numbers10"].stateValues.value.tree).eq(7); + expect(stateVariables["/numbers11"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths00"].stateValues.value.tree).eq(6); + expect(stateVariables["/maths01"].stateValues.value.tree).eq(7); + expect(stateVariables["/maths10"].stateValues.value.tree).eq(7); + expect(stateVariables["/maths11"].stateValues.value.tree).eq(6); + }); + + it("mod", async () => { + let core = await createTestCore({ + doenetML: ` + 173 + 173 + 173 + 173 + 173 + 173 + 176/2 + 176/2 + 176/2 + 17169 + $numbers{name="numbersb"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(2); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect( + stateVariables["/numbersForceSymbolic"].stateValues.value.tree, + ).eqls(["apply", "mod", ["tuple", 17, 3]]); + expect( + stateVariables["/numbersForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/numbersForceSymbolic"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues.value + .tree, + ).eq(2); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.value.tree, + ).eq(2); + expect( + stateVariables["/numbersWithNumberMath"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMath"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .value.tree, + ).eqls(["apply", "mod", ["tuple", 17, 3]]); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(2); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumberMathForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.value.tree, + ).eqls(["apply", "mod", ["tuple", 17, ["/", 6, 2]]]); + expect( + stateVariables["/numbersWithNumericMath"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMath"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues.value + .tree, + ).eq(2); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersWithNumericMathSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .value.tree, + ).eq(2); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numbersWithNumericMathForceNumeric"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/withNumberMod"].stateValues.value.tree).eq(3); + expect( + stateVariables["/withNumberMod"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMod"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersb"].stateValues.value.tree).eq(2); + expect(stateVariables["/numbersb"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbersb"].stateValues.isNumber).eq(true); + }); + + it("mod with sugar", async () => { + let core = await createTestCore({ + doenetML: ` + 17 + 3 + 3 + 6/2 + 173 + 17 3 + 17 3 + 17 3 + 17 6/2 + 17 6/2 + 17 6/2 + $a$b + $a$b + $a$b + $a $b + $a$bNumberMath + $a$bNumberMath + $a$bNumberMath + $a$bNumericMath + $a$bNumericMath + $a$bNumericMath + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numbers"].stateValues.value.tree).eq(2); + expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( + true, + ); + expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.value.tree).eq(2); + expect( + stateVariables["/numbersAsString"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsString"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues.value + .tree, + ).eqls(["apply", "mod", ["tuple", 17, 3]]); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(2); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsStringForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numericAsString"].stateValues.value.tree).eqls([ + "apply", + "mod", + ["tuple", 17, ["/", 6, 2]], + ]); + expect( + stateVariables["/numericAsString"].stateValues.isNumericOperator, + ).eq(false); + expect(stateVariables["/numericAsString"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.value.tree, + ).eq(2); + expect( + stateVariables["/numericAsStringSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numericAsStringSimplify"].stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.value + .tree, + ).eq(2); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/numericAsStringForceNumeric"].stateValues.isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.value.tree).eq(2); + expect( + stateVariables["/numbersAsMacros"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues.value + .tree, + ).eqls(["apply", "mod", ["tuple", 17, 3]]); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .value.tree, + ).eq(2); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/numbersAsMacrosForceSymbolicSimplify"].stateValues + .isNumber, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.value.tree).eq( + 2, + ); + expect( + stateVariables["/numbersAsMacros2"].stateValues.isNumericOperator, + ).eq(true); + expect(stateVariables["/numbersAsMacros2"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacro"].stateValues.value.tree, + ).eq(2); + expect( + stateVariables["/withNumberMathMacro"].stateValues + .isNumericOperator, + ).eq(true); + expect(stateVariables["/withNumberMathMacro"].stateValues.isNumber).eq( + true, + ); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .value.tree, + ).eqls(["apply", "mod", ["tuple", 17, 3]]); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolic"].stateValues + .isNumber, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.value.tree, + ).eq(2); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumberMathMacroForceSymbolicSimplify"] + .stateValues.isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacro"].stateValues.value.tree, + ).eqls(["apply", "mod", ["tuple", 17, ["/", 6, 2]]]); + expect( + stateVariables["/withNumericMathMacro"].stateValues + .isNumericOperator, + ).eq(false); + expect(stateVariables["/withNumericMathMacro"].stateValues.isNumber).eq( + false, + ); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues.value + .tree, + ).eq(2); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumericOperator, + ).eq(false); + expect( + stateVariables["/withNumericMathMacroSimplify"].stateValues + .isNumber, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .value.tree, + ).eq(2); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumericOperator, + ).eq(true); + expect( + stateVariables["/withNumericMathMacroForceNumeric"].stateValues + .isNumber, + ).eq(true); + }); + + it("mod as math expression", async () => { + let core = await createTestCore({ + doenetML: ` + + 17 + 3 + + mod(17,3) + mod(17,3) + + mod(17,3) + + + mod(17,3) + + + mod($a,$b) + + + mod($a,$b) + + + mod($nums) + + + mod($nums) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/numberString"].stateValues.value.tree).eqls([ + "apply", + "mod", + ["tuple", 17, 3], + ]); + expect(stateVariables["/numberString"].stateValues.isNumber).eq(false); + expect( + stateVariables["/numberStringSimplify"].stateValues.value.tree, + ).eq(2); + expect(stateVariables["/numberStringSimplify"].stateValues.isNumber).eq( + true, + ); + + expect( + stateVariables["/numberComponentsCommas"].stateValues.value.tree, + ).eqls(["apply", "mod", ["tuple", 17, 3]]); + expect( + stateVariables["/numberComponentsCommas"].stateValues.isNumber, + ).eq(false); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues.value + .tree, + ).eq(2); + expect( + stateVariables["/numberComponentsCommasSimplify"].stateValues + .isNumber, + ).eq(true); + + expect(stateVariables["/macrosCommas"].stateValues.value.tree).eqls([ + "apply", + "mod", + ["tuple", 17, 3], + ]); + expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq(false); + expect( + stateVariables["/macrosCommasSimplify"].stateValues.value.tree, + ).eq(2); + expect(stateVariables["/macrosCommasSimplify"].stateValues.isNumber).eq( + true, + ); + + expect(stateVariables["/group"].stateValues.value.tree).eqls([ + "apply", + "mod", + ["tuple", 17, 3], + ]); + expect(stateVariables["/group"].stateValues.isNumber).eq(false); + expect(stateVariables["/groupSimplify"].stateValues.value.tree).eq(2); + expect(stateVariables["/groupSimplify"].stateValues.isNumber).eq(true); + }); + + it("gcd", async () => { + let core = await createTestCore({ + doenetML: ` + 13581 + 135 81 63 + x y z + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/_gcd1"].stateValues.value.tree).eq(27); + expect(stateVariables["/_gcd2"].stateValues.value.tree).eq(9); + expect(stateVariables["/_gcd3"].stateValues.value.tree).eqls([ + "apply", + "gcd", + ["tuple", "x", "y", "z"], + ]); + }); + + it("extract parts of math expression", async () => { + let core = await createTestCore({ + doenetML: ` + a +

original expression: f(x)+g(y,z)+h(q)

+

Operator: $expr

+

Number of operands: $expr

+

First operand: $expr

+

Second operand: $expr

+

Third operand: $expr

+

No fourth operand: $expr

+

Function from first operand: $operand1

+

Function from second operand: $operand2

+

No function from third operand: $operand3

+

Function argument from first operand: $operand1

+

Function argument from first operand again: $operand1

+

No second function argument from first operand: $operand1

+

All function arguments from second operand: $operand2

+

First function argument from second operand: $operand2

+

Second function argument from second operand: $operand2

+

No third function argument from second operand: $operand2

+

No function argument from third operand: $operand3

+

Number of operands from first operand: $operand1

+

First operand from first operand: $operand1

+ + +

Pick operand number:

+

Resulting operand: $expr

+

Function of resulting operand: $operandN

+

Pick argument number:

+

Resulting argument: $operandN

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/operator"].stateValues.value).eq("+"); + expect(stateVariables["/numOperands"].stateValues.value.tree).eq(3); + expect(stateVariables["/operand1"].stateValues.value.tree).eqls([ + "apply", + "f", + "x", + ]); + expect(stateVariables["/operand2"].stateValues.value.tree).eqls([ + "apply", + "g", + ["tuple", "y", "z"], + ]); + expect(stateVariables["/operand3"].stateValues.value.tree).eqls([ + "*", + "h", + "q", + ]); + expect(stateVariables["/blank1"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/f"].stateValues.value.tree).eqls("f"); + expect(stateVariables["/g"].stateValues.value.tree).eqls("g"); + expect(stateVariables["/blank2"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/farg1"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/farg1a"].stateValues.value.tree).eqls("x"); + expect(stateVariables["/blank3"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/gargAll"].stateValues.value.tree).eqls([ + "tuple", + "y", + "z", + ]); + expect(stateVariables["/garg1"].stateValues.value.tree).eqls("y"); + expect(stateVariables["/garg2"].stateValues.value.tree).eqls("z"); + expect(stateVariables["/blank4"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/blank5"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/numOperands1"].stateValues.value.tree).eq(1); + expect(stateVariables["/operand11"].stateValues.value.tree).eqls([ + "apply", + "f", + "x", + ]); + + expect(stateVariables["/operandN"].stateValues.value.tree).eqls([ + "apply", + "f", + "x", + ]); + expect(stateVariables["/functionN"].stateValues.value.tree).eqls("f"); + expect(stateVariables["/argumentN"].stateValues.value.tree).eqls("x"); + + await updateMathInputValue({ + latex: "2", + componentName: "/nArgument", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/argumentN"].stateValues.value.tree).eqls("οΌΏ"); + + await updateMathInputValue({ + latex: "2", + componentName: "/nOperand", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/operandN"].stateValues.value.tree).eqls([ + "apply", + "g", + ["tuple", "y", "z"], + ]); + expect(stateVariables["/functionN"].stateValues.value.tree).eqls("g"); + expect(stateVariables["/argumentN"].stateValues.value.tree).eqls("z"); + + await updateMathInputValue({ + latex: "3", + componentName: "/nArgument", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/argumentN"].stateValues.value.tree).eqls("οΌΏ"); + + await updateMathInputValue({ + latex: "1", + componentName: "/nArgument", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/argumentN"].stateValues.value.tree).eqls("y"); + + await updateMathInputValue({ + latex: "3", + componentName: "/nOperand", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/operandN"].stateValues.value.tree).eqls([ + "*", + "h", + "q", + ]); + expect(stateVariables["/functionN"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/argumentN"].stateValues.value.tree).eqls("οΌΏ"); + + await updateMathInputValue({ + latex: "4", + componentName: "/nOperand", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/operandN"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/functionN"].stateValues.value.tree).eqls("οΌΏ"); + expect(stateVariables["/argumentN"].stateValues.value.tree).eqls("οΌΏ"); + }); + + it("warning with operand", async () => { + let core = await createTestCore({ + doenetML: ` +

original expression: x+y

+

Bad operand: $expr

+ `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(1); + + expect(errorWarnings.warnings[0].message).contain( + `Must specify a operandNumber when extracting a math operand`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(3); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(23); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(3); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(85); + }); + + it("math operators that take multiple inputs ignore composites with no replacements", async () => { + let core = await createTestCore({ + doenetML: ` + (x+1)(x-2)(x-4) +

Min on [0,2]: $$f(0) $(f.minimumValues) $$f(2).

+

Abs treats as product of three factors: $$f(0) $(f.minimumValues) $$f(2).

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/min02"].stateValues.value.tree).eq(0); + expect(stateVariables["/abs"].stateValues.value.tree).eqls([ + "apply", + "abs", + ["*", 8, "οΌΏ", 0], + ]); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/number.test.ts b/packages/doenetml-worker/src/test/tagSpecific/number.test.ts new file mode 100644 index 000000000..b87a8bcfa --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/number.test.ts @@ -0,0 +1,1960 @@ +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("Number tag tests", async () => { + it("1+1", async () => { + let core = await createTestCore({ + doenetML: ` + $_number1{name="num"} + 1+1 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/num"].stateValues.value).eq(2); + expect(stateVariables["/_number1"].stateValues.value).eq(2); + }); + + it(`number that isn't a number`, async () => { + let core = await createTestCore({ + doenetML: ` + $_number1{name="num"} + x+1 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/num"].stateValues.value).eqls(NaN); + expect(stateVariables["/_number1"].stateValues.value).eqls(NaN); + }); + + it(`number becomes non-numeric through inverse`, async () => { + let core = await createTestCore({ + doenetML: ` + 5 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(5); + + await updateMathInputValue({ latex: "x", componentName: "/mi", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eqls(NaN); + + await updateMathInputValue({ latex: "9", componentName: "/mi", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(9); + }); + + it("number in math", async () => { + let core = await createTestCore({ + doenetML: ` + x+3 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + "x", + 3, + ]); + expect(stateVariables["/_number1"].stateValues.value).to.eq(3); + }); + + it("math in number", async () => { + let core = await createTestCore({ + doenetML: ` + 5+3 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_math1"].stateValues.value.tree).eqls([ + "+", + 5, + 3, + ]); + expect(stateVariables["/_math2"].stateValues.value.tree).eq(3); + expect(stateVariables["/_number1"].stateValues.value).eq(8); + }); + + it("number converts to decimals", async () => { + let core = await createTestCore({ + doenetML: ` + log(0.5/0.3), + $_number1 + `, + }); + + let num = Math.log(0.5 / 0.3); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_math1"].stateValues.value.tree).closeTo( + num, + 1e-14, + ); + expect(stateVariables["/_number1"].stateValues.value).closeTo( + num, + 1e-14, + ); + }); + + it("rounding", async () => { + let core = await createTestCore({ + doenetML: ` + 234234823.34235235324 + 5.4285023408250342 + 0.000000000000005023481340324 + $n1{displayDigits='5' name="n1a"} + $n1{displayDecimals='3' name="n1b"} + $n1{displayDigits='5' displayDecimals='3' displaySmallAsZero="false" name="n1c"} + $n2{displayDigits='5' name="n2a"} + $n2{displayDecimals='3' name="n2b"} + $n2{displayDigits='5' displayDecimals='3' displaySmallAsZero="false" name="n2c"} + $n3{displayDigits='5' name="n3a"} + $n3{displayDecimals='3' name="n3b"} + $n3{displayDigits='5' displayDecimals='3' displaySmallAsZero="false" name="n3c"} + + $n1a{name="n1aa"} + $n1a{displayDecimals='3' name="n1ab"} + $n2a{name="n2aa"} + $n2a{displayDecimals='3' name="n2ab"} + $n3a{displaySmallAsZero="false" name="n3aa"} + $n3a{displayDecimals='3' displaySmallAsZero="false" name="n3ab"} + + $n1b{name="n1ba"} + $n1b{displayDigits='5' name="n1bb"} + $n2b{name="n2ba"} + $n2b{displayDigits='5' name="n2bb"} + $n3b{displaySmallAsZero="false" name="n3ba"} + $n3b{displayDigits='5' displayDecimals='3' displaySmallAsZero="false" name="n3bb"} + + $n1a + $n1b + $n1c + $n2a + $n2b + $n2c + $n3a + $n3b + $n3c + + $n1aa + $n1ab + $n2aa + $n2ab + $n3aa + $n3ab + + $n1ba + $n1bb + $n2ba + $n2bb + $n3ba + $n3bb + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n1"].stateValues.text).eq("234234823.34"); + expect(stateVariables["/n1a"].stateValues.text).eq("234230000"); + expect(stateVariables["/n1b"].stateValues.text).eq("234234823.342"); + expect(stateVariables["/n1c"].stateValues.text).eq("234234823.342"); + + expect(cleanLatex(stateVariables["/n1am"].stateValues.latex)).eq( + "234230000", + ); + expect(cleanLatex(stateVariables["/n1bm"].stateValues.latex)).eq( + "234234823.342", + ); + expect(cleanLatex(stateVariables["/n1cm"].stateValues.latex)).eq( + "234234823.342", + ); + + expect(stateVariables["/n2"].stateValues.text).eq("5.43"); + expect(stateVariables["/n2a"].stateValues.text).eq("5.4285"); + expect(stateVariables["/n2b"].stateValues.text).eq("5.429"); + expect(stateVariables["/n2c"].stateValues.text).eq("5.4285"); + expect(cleanLatex(stateVariables["/n2am"].stateValues.latex)).eq( + "5.4285", + ); + expect(cleanLatex(stateVariables["/n2bm"].stateValues.latex)).eq( + "5.429", + ); + expect(cleanLatex(stateVariables["/n2cm"].stateValues.latex)).eq( + "5.4285", + ); + + expect(stateVariables["/n3"].stateValues.text).eq("0"); + expect(stateVariables["/n3a"].stateValues.text).eq("0"); + expect(stateVariables["/n3b"].stateValues.text).eq("0"); + expect(stateVariables["/n3c"].stateValues.text).eq("5.0235 * 10^(-15)"); + expect(cleanLatex(stateVariables["/n3am"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/n3bm"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/n3cm"].stateValues.latex)).eq( + "5.0235\\cdot10^{-15}", + ); + + expect(stateVariables["/n1aa"].stateValues.text).eq("234230000"); + expect(stateVariables["/n1ab"].stateValues.text).eq("234234823.342"); + expect(cleanLatex(stateVariables["/n1aam"].stateValues.latex)).eq( + "234230000", + ); + expect(cleanLatex(stateVariables["/n1abm"].stateValues.latex)).eq( + "234234823.342", + ); + + expect(stateVariables["/n2aa"].stateValues.text).eq("5.4285"); + expect(stateVariables["/n2ab"].stateValues.text).eq("5.429"); + expect(cleanLatex(stateVariables["/n2aam"].stateValues.latex)).eq( + "5.4285", + ); + expect(cleanLatex(stateVariables["/n2abm"].stateValues.latex)).eq( + "5.429", + ); + + expect(stateVariables["/n3aa"].stateValues.text).eq( + "5.0235 * 10^(-15)", + ); + expect(stateVariables["/n3ab"].stateValues.text).eq("0"); + expect(cleanLatex(stateVariables["/n3aam"].stateValues.latex)).eq( + "5.0235\\cdot10^{-15}", + ); + expect(cleanLatex(stateVariables["/n3abm"].stateValues.latex)).eq("0"); + + expect(stateVariables["/n1ba"].stateValues.text).eq("234234823.342"); + expect(stateVariables["/n1bb"].stateValues.text).eq("234230000"); + expect(cleanLatex(stateVariables["/n1bam"].stateValues.latex)).eq( + "234234823.342", + ); + expect(cleanLatex(stateVariables["/n1bbm"].stateValues.latex)).eq( + "234230000", + ); + + expect(stateVariables["/n2ba"].stateValues.text).eq("5.429"); + expect(stateVariables["/n2bb"].stateValues.text).eq("5.4285"); + expect(cleanLatex(stateVariables["/n2bam"].stateValues.latex)).eq( + "5.429", + ); + expect(cleanLatex(stateVariables["/n2bbm"].stateValues.latex)).eq( + "5.4285", + ); + + expect(stateVariables["/n3ba"].stateValues.text).eq("0"); + expect(stateVariables["/n3bb"].stateValues.text).eq( + "5.0235 * 10^(-15)", + ); + expect(cleanLatex(stateVariables["/n3bam"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/n3bbm"].stateValues.latex)).eq( + "5.0235\\cdot10^{-15}", + ); + + expect(stateVariables["/n1"].stateValues.value).eq( + 234234823.34235235324, + ); + expect(stateVariables["/n1a"].stateValues.value).eq( + 234234823.34235235324, + ); + expect(stateVariables["/n1b"].stateValues.value).eq( + 234234823.34235235324, + ); + expect(stateVariables["/n1c"].stateValues.value).eq( + 234234823.34235235324, + ); + expect( + stateVariables[ + stateVariables["/n1am"].activeChildren[0].componentName + ].stateValues.value, + ).eq(234234823.34235235324); + expect( + stateVariables[ + stateVariables["/n1bm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(234234823.34235235324); + expect( + stateVariables[ + stateVariables["/n1cm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(234234823.34235235324); + expect(stateVariables["/n2"].stateValues.value).eq(5.4285023408250342); + expect(stateVariables["/n2a"].stateValues.value).eq(5.4285023408250342); + expect(stateVariables["/n2b"].stateValues.value).eq(5.4285023408250342); + expect(stateVariables["/n2c"].stateValues.value).eq(5.4285023408250342); + expect( + stateVariables[ + stateVariables["/n2am"].activeChildren[0].componentName + ].stateValues.value, + ).eq(5.4285023408250342); + expect( + stateVariables[ + stateVariables["/n2bm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(5.4285023408250342); + expect( + stateVariables[ + stateVariables["/n2cm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(5.4285023408250342); + expect(stateVariables["/n3"].stateValues.value).eq( + 0.000000000000005023481340324, + ); + expect(stateVariables["/n3a"].stateValues.value).eq( + 0.000000000000005023481340324, + ); + expect(stateVariables["/n3b"].stateValues.value).eq( + 0.000000000000005023481340324, + ); + expect(stateVariables["/n3c"].stateValues.value).eq( + 0.000000000000005023481340324, + ); + expect( + stateVariables[ + stateVariables["/n3am"].activeChildren[0].componentName + ].stateValues.value, + ).eq(0.000000000000005023481340324); + expect( + stateVariables[ + stateVariables["/n3bm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(0.000000000000005023481340324); + expect( + stateVariables[ + stateVariables["/n3cm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(0.000000000000005023481340324); + + expect(stateVariables["/n1aa"].stateValues.value).eq( + 234234823.34235235324, + ); + expect(stateVariables["/n1ab"].stateValues.value).eq( + 234234823.34235235324, + ); + expect( + stateVariables[ + stateVariables["/n1aam"].activeChildren[0].componentName + ].stateValues.value, + ).eq(234234823.34235235324); + expect( + stateVariables[ + stateVariables["/n1abm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(234234823.34235235324); + expect(stateVariables["/n2aa"].stateValues.value).eq( + 5.4285023408250342, + ); + expect(stateVariables["/n2ab"].stateValues.value).eq( + 5.4285023408250342, + ); + expect( + stateVariables[ + stateVariables["/n2aam"].activeChildren[0].componentName + ].stateValues.value, + ).eq(5.4285023408250342); + expect( + stateVariables[ + stateVariables["/n2abm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(5.4285023408250342); + expect(stateVariables["/n3aa"].stateValues.value).eq( + 0.000000000000005023481340324, + ); + expect(stateVariables["/n3ab"].stateValues.value).eq( + 0.000000000000005023481340324, + ); + expect( + stateVariables[ + stateVariables["/n3aam"].activeChildren[0].componentName + ].stateValues.value, + ).eq(0.000000000000005023481340324); + expect( + stateVariables[ + stateVariables["/n3abm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(0.000000000000005023481340324); + + expect(stateVariables["/n1ba"].stateValues.value).eq( + 234234823.34235235324, + ); + expect(stateVariables["/n1bb"].stateValues.value).eq( + 234234823.34235235324, + ); + expect( + stateVariables[ + stateVariables["/n1bam"].activeChildren[0].componentName + ].stateValues.value, + ).eq(234234823.34235235324); + expect( + stateVariables[ + stateVariables["/n1bbm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(234234823.34235235324); + expect(stateVariables["/n2ba"].stateValues.value).eq( + 5.4285023408250342, + ); + expect(stateVariables["/n2bb"].stateValues.value).eq( + 5.4285023408250342, + ); + expect( + stateVariables[ + stateVariables["/n2bam"].activeChildren[0].componentName + ].stateValues.value, + ).eq(5.4285023408250342); + expect( + stateVariables[ + stateVariables["/n2bbm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(5.4285023408250342); + expect(stateVariables["/n3ba"].stateValues.value).eq( + 0.000000000000005023481340324, + ); + expect(stateVariables["/n3bb"].stateValues.value).eq( + 0.000000000000005023481340324, + ); + expect( + stateVariables[ + stateVariables["/n3bam"].activeChildren[0].componentName + ].stateValues.value, + ).eq(0.000000000000005023481340324); + expect( + stateVariables[ + stateVariables["/n3bbm"].activeChildren[0].componentName + ].stateValues.value, + ).eq(0.000000000000005023481340324); + }); + + it("pad zeros with rounding", async () => { + let core = await createTestCore({ + doenetML: ` + 22 + 0.000000000000005 + $n1{displayDigits='4' name="n1a"} + $n1{displayDigits='4' name="n1apad" padZeros} + $n1{displayDecimals='3' name="n1b"} + $n1{displayDecimals='3' name="n1bpad" padZeros} + $n1{displayDigits='4' displaySmallAsZero name="n1c"} + $n1{displayDigits='4' displaySmallAsZero name="n1cpad" padZeros} + $n2{displayDigits='4' name="n2a"} + $n2{displayDigits='4' name="n2apad" padZeros} + $n2{displayDecimals='3' name="n2b"} + $n2{displayDecimals='3' name="n2bpad" padZeros} + $n2{displayDigits='4' displaySmallAsZero name="n2c"} + $n2{displayDigits='4' displaySmallAsZero name="n2cpad" padZeros} + + $n1a + $n1apad + $n1b + $n1bpad + $n1c + $n1cpad + $n2a + $n2apad + $n2b + $n2bpad + $n2c + $n2cpad + + $n1a + $n1apad + $n1b + $n1bpad + $n1c + $n1cpad + $n2a + $n2apad + $n2b + $n2bpad + $n2c + $n2cpad + + $n1a + $n1apad + $n1b + $n1bpad + $n1c + $n1cpad + $n2a + $n2apad + $n2b + $n2bpad + $n2c + $n2cpad + + $n1a.value{assignNames="n1aValue"} + $n1apad.value{assignNames="n1apadValue"} + $n1b.value{assignNames="n1bValue"} + $n1bpad.value{assignNames="n1bpadValue"} + $n1c.value{assignNames="n1cValue"} + $n1cpad.value{assignNames="n1cpadValue"} + $n2a.value{assignNames="n2aValue"} + $n2apad.value{assignNames="n2apadValue"} + $n2b.value{assignNames="n2bValue"} + $n2bpad.value{assignNames="n2bpadValue"} + $n2c.value{assignNames="n2cValue"} + $n2cpad.value{assignNames="n2cpadValue"} + + $n1a.text{assignNames="n1aText"} + $n1apad.text{assignNames="n1apadText"} + $n1b.text{assignNames="n1bText"} + $n1bpad.text{assignNames="n1bpadText"} + $n1c.text{assignNames="n1cText"} + $n1cpad.text{assignNames="n1cpadText"} + $n2a.text{assignNames="n2aText"} + $n2apad.text{assignNames="n2apadText"} + $n2b.text{assignNames="n2bText"} + $n2bpad.text{assignNames="n2bpadText"} + $n2c.text{assignNames="n2cText"} + $n2cpad.text{assignNames="n2cpadText"} + + $n1a.math{assignNames="n1aMath2"} + $n1apad.math{assignNames="n1apadMath2"} + $n1b.math{assignNames="n1bMath2"} + $n1bpad.math{assignNames="n1bpadMath2"} + $n1c.math{assignNames="n1cMath2"} + $n1cpad.math{assignNames="n1cpadMath2"} + $n2a.math{assignNames="n2aMath2"} + $n2apad.math{assignNames="n2apadMath2"} + $n2b.math{assignNames="n2bMath2"} + $n2bpad.math{assignNames="n2bpadMath2"} + $n2c.math{assignNames="n2cMath2"} + $n2cpad.math{assignNames="n2cpadMath2"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n1"].stateValues.text).eq("22"); + expect(stateVariables["/n1a"].stateValues.text).eq("22"); + expect(stateVariables["/n1apad"].stateValues.text).eq("22.00"); + expect(stateVariables["/n1b"].stateValues.text).eq("22"); + expect(stateVariables["/n1bpad"].stateValues.text).eq("22.000"); + expect(stateVariables["/n1c"].stateValues.text).eq("22"); + expect(stateVariables["/n1cpad"].stateValues.text).eq("22.00"); + expect(stateVariables["/n2"].stateValues.text).eq("5 * 10^(-15)"); + expect(stateVariables["/n2a"].stateValues.text).eq("5 * 10^(-15)"); + expect(stateVariables["/n2apad"].stateValues.text).eq( + "5.000 * 10^(-15)", + ); + expect(stateVariables["/n2b"].stateValues.text).eq("0"); + expect(stateVariables["/n2bpad"].stateValues.text).eq("0.000"); + expect(stateVariables["/n2c"].stateValues.text).eq("0"); + expect(stateVariables["/n2cpad"].stateValues.text).eq("0.000"); + + expect(cleanLatex(stateVariables["/n1am"].stateValues.latex)).eq("22"); + expect(cleanLatex(stateVariables["/n1apadm"].stateValues.latex)).eq( + "22.00", + ); + expect(cleanLatex(stateVariables["/n1bm"].stateValues.latex)).eq("22"); + expect(cleanLatex(stateVariables["/n1bpadm"].stateValues.latex)).eq( + "22.000", + ); + expect(cleanLatex(stateVariables["/n1cm"].stateValues.latex)).eq("22"); + expect(cleanLatex(stateVariables["/n1cpadm"].stateValues.latex)).eq( + "22.00", + ); + expect(cleanLatex(stateVariables["/n2am"].stateValues.latex)).eq( + "5\\cdot10^{-15}", + ); + expect(cleanLatex(stateVariables["/n2apadm"].stateValues.latex)).eq( + "5.000\\cdot10^{-15}", + ); + expect(cleanLatex(stateVariables["/n2bm"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/n2bpadm"].stateValues.latex)).eq( + "0.000", + ); + expect(cleanLatex(stateVariables["/n2cm"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/n2cpadm"].stateValues.latex)).eq( + "0.000", + ); + + expect(stateVariables["/n1aNumber"].stateValues.text).eq("22"); + expect(stateVariables["/n1apadNumber"].stateValues.text).eq("22.00"); + expect(stateVariables["/n1bNumber"].stateValues.text).eq("22"); + expect(stateVariables["/n1bpadNumber"].stateValues.text).eq("22.000"); + expect(stateVariables["/n1cNumber"].stateValues.text).eq("22"); + expect(stateVariables["/n1cpadNumber"].stateValues.text).eq("22.00"); + expect(stateVariables["/n2aNumber"].stateValues.text).eq( + "5 * 10^(-15)", + ); + expect(stateVariables["/n2apadNumber"].stateValues.text).eq( + "5.000 * 10^(-15)", + ); + expect(stateVariables["/n2bNumber"].stateValues.text).eq("0"); + expect(stateVariables["/n2bpadNumber"].stateValues.text).eq("0.000"); + expect(stateVariables["/n2cNumber"].stateValues.text).eq("0"); + expect(stateVariables["/n2cpadNumber"].stateValues.text).eq("0.000"); + + expect(cleanLatex(stateVariables["/n1aMath"].stateValues.latex)).eq( + "22", + ); + expect(cleanLatex(stateVariables["/n1apadMath"].stateValues.latex)).eq( + "22.00", + ); + expect(cleanLatex(stateVariables["/n1bMath"].stateValues.latex)).eq( + "22", + ); + expect(cleanLatex(stateVariables["/n1bpadMath"].stateValues.latex)).eq( + "22.000", + ); + expect(cleanLatex(stateVariables["/n1cMath"].stateValues.latex)).eq( + "22", + ); + expect(cleanLatex(stateVariables["/n1cpadMath"].stateValues.latex)).eq( + "22.00", + ); + expect(cleanLatex(stateVariables["/n2aMath"].stateValues.latex)).eq( + "5\\cdot10^{-15}", + ); + expect(cleanLatex(stateVariables["/n2apadMath"].stateValues.latex)).eq( + "5.000\\cdot10^{-15}", + ); + expect(cleanLatex(stateVariables["/n2bMath"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/n2bpadMath"].stateValues.latex)).eq( + "0.000", + ); + expect(cleanLatex(stateVariables["/n2cMath"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/n2cpadMath"].stateValues.latex)).eq( + "0.000", + ); + + expect(stateVariables["/n1aValue"].stateValues.text).eq("22"); + expect(stateVariables["/n1apadValue"].stateValues.text).eq("22.00"); + expect(stateVariables["/n1bValue"].stateValues.text).eq("22"); + expect(stateVariables["/n1bpadValue"].stateValues.text).eq("22.000"); + expect(stateVariables["/n1cValue"].stateValues.text).eq("22"); + expect(stateVariables["/n1cpadValue"].stateValues.text).eq("22.00"); + expect(stateVariables["/n2aValue"].stateValues.text).eq("5 * 10^(-15)"); + expect(stateVariables["/n2apadValue"].stateValues.text).eq( + "5.000 * 10^(-15)", + ); + expect(stateVariables["/n2bValue"].stateValues.text).eq("0"); + expect(stateVariables["/n2bpadValue"].stateValues.text).eq("0.000"); + expect(stateVariables["/n2cValue"].stateValues.text).eq("0"); + expect(stateVariables["/n2cpadValue"].stateValues.text).eq("0.000"); + + expect(stateVariables["/n1aText"].stateValues.text).eq("22"); + expect(stateVariables["/n1apadText"].stateValues.text).eq("22.00"); + expect(stateVariables["/n1bText"].stateValues.text).eq("22"); + expect(stateVariables["/n1bpadText"].stateValues.text).eq("22.000"); + expect(stateVariables["/n1cText"].stateValues.text).eq("22"); + expect(stateVariables["/n1cpadText"].stateValues.text).eq("22.00"); + expect(stateVariables["/n2aText"].stateValues.text).eq("5 * 10^(-15)"); + expect(stateVariables["/n2apadText"].stateValues.text).eq( + "5.000 * 10^(-15)", + ); + expect(stateVariables["/n2bText"].stateValues.text).eq("0"); + expect(stateVariables["/n2bpadText"].stateValues.text).eq("0.000"); + expect(stateVariables["/n2cText"].stateValues.text).eq("0"); + expect(stateVariables["/n2cpadText"].stateValues.text).eq("0.000"); + + expect(cleanLatex(stateVariables["/n1aMath2"].stateValues.latex)).eq( + "22", + ); + expect(cleanLatex(stateVariables["/n1apadMath2"].stateValues.latex)).eq( + "22.00", + ); + expect(cleanLatex(stateVariables["/n1bMath2"].stateValues.latex)).eq( + "22", + ); + expect(cleanLatex(stateVariables["/n1bpadMath2"].stateValues.latex)).eq( + "22.000", + ); + expect(cleanLatex(stateVariables["/n1cMath2"].stateValues.latex)).eq( + "22", + ); + expect(cleanLatex(stateVariables["/n1cpadMath2"].stateValues.latex)).eq( + "22.00", + ); + expect(cleanLatex(stateVariables["/n2aMath2"].stateValues.latex)).eq( + "5\\cdot10^{-15}", + ); + expect(cleanLatex(stateVariables["/n2apadMath2"].stateValues.latex)).eq( + "5.000\\cdot10^{-15}", + ); + expect(cleanLatex(stateVariables["/n2bMath2"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/n2bpadMath2"].stateValues.latex)).eq( + "0.000", + ); + expect(cleanLatex(stateVariables["/n2cMath2"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/n2cpadMath2"].stateValues.latex)).eq( + "0.000", + ); + }); + + it("dynamic rounding", async () => { + let core = await createTestCore({ + doenetML: ` +

Number: 35203423.02352343201

+

Number of digits:

+

Number of decimals:

+

$n{displayDigits='$ndigits' displayDecimals='$ndecimals' name="na"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.text).eq("35203423.02"); + expect(stateVariables["/na"].stateValues.text).eq("35203423.024"); + + // only digits + await updateMathInputValue({ + latex: "-\\infty", + componentName: "/ndecimals", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/na"].stateValues.text).eq("35200000"); + + // more digits + await updateMathInputValue({ + latex: "12", + componentName: "/ndigits", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/na"].stateValues.text).eq("35203423.0235"); + + // remove digits + await updateMathInputValue({ + latex: "0", + componentName: "/ndigits", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/na"].stateValues.text).eq("35203423.023523435"); + + // Fewer digits than have + await updateMathInputValue({ + latex: "-10", + componentName: "/ndecimals", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/na"].stateValues.text).eq("0"); + + // add one digit + await updateMathInputValue({ + latex: "1", + componentName: "/ndigits", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/na"].stateValues.text).eq("40000000"); + + // invalid precision means no rounding + await updateMathInputValue({ + latex: "x", + componentName: "/ndigits", + core, + }); + await updateMathInputValue({ + latex: "y", + componentName: "/ndecimals", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/na"].stateValues.text).eq("35203423.023523435"); + + // add a decimal + await updateMathInputValue({ + latex: "1", + componentName: "/ndecimals", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/na"].stateValues.text).eq("35203423"); + + // negative precision, ignores display digits + await updateMathInputValue({ + latex: "-3", + componentName: "/ndigits", + core, + }); + await updateMathInputValue({ + latex: "-3", + componentName: "/ndecimals", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/na"].stateValues.text).eq("35203000"); + }); + + it("infinity and nan", async () => { + let core = await createTestCore({ + doenetML: ` + a + Infinity + Infinity+Infinity + 1/0 + -2/-0 + Infinity + Infinity+Infinity + 5/0 + -6/-0 + + -Infinity + -3/0 + 4/-0 + -Infinity + -8/0 + 7/-0 + + Infinity-Infinity + Infinity/Infinity + 0/0 + -0/0 + -Infinity+Infinity + Infinity/Infinity + 0/0 + 0/-0 + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/inf1"].stateValues.value).eq(Infinity); + expect(stateVariables["/inf2"].stateValues.value).eq(Infinity); + expect(stateVariables["/inf3"].stateValues.value).eq(Infinity); + expect(stateVariables["/inf4"].stateValues.value).eq(Infinity); + expect(stateVariables["/inf5"].stateValues.value).eq(Infinity); + expect(stateVariables["/inf6"].stateValues.value).eq(Infinity); + expect(stateVariables["/inf7"].stateValues.value).eq(Infinity); + expect(stateVariables["/inf8"].stateValues.value).eq(Infinity); + + expect(stateVariables["/ninf1"].stateValues.value).eq(-Infinity); + expect(stateVariables["/ninf2"].stateValues.value).eq(-Infinity); + expect(stateVariables["/ninf3"].stateValues.value).eq(-Infinity); + expect(stateVariables["/ninf4"].stateValues.value).eq(-Infinity); + expect(stateVariables["/ninf5"].stateValues.value).eq(-Infinity); + expect(stateVariables["/ninf6"].stateValues.value).eq(-Infinity); + + expect(stateVariables["/nan1"].stateValues.value).eqls(NaN); + expect(stateVariables["/nan2"].stateValues.value).eqls(NaN); + expect(stateVariables["/nan3"].stateValues.value).eqls(NaN); + expect(stateVariables["/nan4"].stateValues.value).eqls(NaN); + expect(stateVariables["/nan5"].stateValues.value).eqls(NaN); + expect(stateVariables["/nan6"].stateValues.value).eqls(NaN); + expect(stateVariables["/nan7"].stateValues.value).eqls(NaN); + expect(stateVariables["/nan8"].stateValues.value).eqls(NaN); + }); + + it("copy value prop copies attributes", async () => { + let core = await createTestCore({ + doenetML: ` +

8.5203845251 + $n1.value{assignNames="n1a"} + $n1.value{displayDigits="5" assignNames="n1b"} + $n1.value{link="false" assignNames="n1c"} + $n1.value{link="false" displayDigits="5" assignNames="n1d"} +

+ +

8.5203845251 + $n2.value{assignNames="n2a"} + $n2.value{displayDecimals="6" assignNames="n2b"} + $n2.value{link="false" assignNames="n2c"} + $n2.value{link="false" displayDecimals="6" assignNames="n2d"} +

+ +

0.000000000000000015382487 + $n3.value{assignNames="n3a"} + $n3.value{displaySmallAsZero assignNames="n3b"} + $n3.value{link="false" assignNames="n3c"} + $n3.value{link="false" displaySmallAsZero assignNames="n3d"} +

+ +

8 + $n4.value{assignNames="n4a"} + $n4.value{padZeros="false" assignNames="n4b"} + $n4.value{link="false" assignNames="n4c"} + $n4.value{link="false" padZeros="false" assignNames="n4d"} +

+ + `, + }); + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n1"].stateValues.text).eq("8.5"); + expect(stateVariables["/n1a"].stateValues.text).eq("8.5"); + expect(stateVariables["/n1b"].stateValues.text).eq("8.5204"); + expect(stateVariables["/n1c"].stateValues.text).eq("8.5"); + expect(stateVariables["/n1d"].stateValues.text).eq("8.5204"); + + expect(stateVariables["/n2"].stateValues.text).eq("9"); + expect(stateVariables["/n2a"].stateValues.text).eq("9"); + expect(stateVariables["/n2b"].stateValues.text).eq("8.520385"); + expect(stateVariables["/n2c"].stateValues.text).eq("9"); + expect(stateVariables["/n2d"].stateValues.text).eq("8.520385"); + + expect(stateVariables["/n3"].stateValues.text).eq("1.54 * 10^(-17)"); + expect(stateVariables["/n3a"].stateValues.text).eq("1.54 * 10^(-17)"); + expect(stateVariables["/n3b"].stateValues.text).eq("0"); + expect(stateVariables["/n3c"].stateValues.text).eq("1.54 * 10^(-17)"); + expect(stateVariables["/n3d"].stateValues.text).eq("0"); + + expect(stateVariables["/n4"].stateValues.text).eq("8.00"); + expect(stateVariables["/n4a"].stateValues.text).eq("8.00"); + expect(stateVariables["/n4b"].stateValues.text).eq("8"); + expect(stateVariables["/n4c"].stateValues.text).eq("8.00"); + expect(stateVariables["/n4d"].stateValues.text).eq("8"); + }); + + it("display rounding preserved when only one number or math child", async () => { + let core = await createTestCore({ + doenetML: ` +

8.5203845251 + 8.5203845251 + 8.52038452512.8392634947 + 8.52038452512.8392634947 + 8.52038452512.8392634947 + 8.52038452512.8392634947 + 8.5203845251 + 8.5203845251 +

+ +

+ + + + + + + +

+ +

8.5203845251 + 8.5203845251 + 8.52038452512.8392634947 + 8.52038452512.8392634947 + 8.52038452512.8392634947 + 8.52038452512.8392634947 + 8.5203845251 + 8.5203845251 +

+ +

+ + + + + + + +

+ +

0.000000000000000015382487 + 0.000000000000000015382487 + 0.0000000000000000153824872.8392634947 + 0.0000000000000000153824872.8392634947 + 0.0000000000000000153824872.8392634947 + 0.0000000000000000153824872.8392634947 + 0.000000000000000015382487 +

+ +

+ + + + + + +

+ +

8 + 8 + 82 + 82 + 82 + 82 + 8 +

+ +

+ + + + + + +

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m1"].stateValues.text).eq("8.5"); + expect(stateVariables["/m1a"].stateValues.text).eq("8.5"); + expect(stateVariables["/m1b"].stateValues.text).eq("24.19"); + expect(stateVariables["/m1c"].stateValues.text).eq("24.19"); + expect(stateVariables["/m1d"].stateValues.text).eq("24.19"); + expect(stateVariables["/m1e"].stateValues.text).eq("24.19"); + expect(stateVariables["/m1f"].stateValues.text).eq("9"); + expect(stateVariables["/m1g"].stateValues.text).eq("8.52038453"); + + expect(stateVariables["/m1_v"].stateValues.text).eq("8.5"); + expect(stateVariables["/m1a_v"].stateValues.text).eq("8.5"); + expect(stateVariables["/m1b_v"].stateValues.text).eq("24.19"); + expect(stateVariables["/m1c_v"].stateValues.text).eq("24.19"); + expect(stateVariables["/m1d_v"].stateValues.text).eq("24.19"); + expect(stateVariables["/m1e_v"].stateValues.text).eq("24.19"); + expect(stateVariables["/m1f_v"].stateValues.text).eq("9"); + expect(stateVariables["/m1g_v"].stateValues.text).eq("8.52038453"); + + expect(stateVariables["/m2"].stateValues.text).eq("8.5204"); + expect(stateVariables["/m2a"].stateValues.text).eq("8.5204"); + expect(stateVariables["/m2b"].stateValues.text).eq("24.19"); + expect(stateVariables["/m2c"].stateValues.text).eq("24.19"); + expect(stateVariables["/m2d"].stateValues.text).eq("24.19"); + expect(stateVariables["/m2e"].stateValues.text).eq("24.19"); + expect(stateVariables["/m2f"].stateValues.text).eq("8.520385"); + expect(stateVariables["/m2g"].stateValues.text).eq("8.5203845"); + + expect(stateVariables["/m2_v"].stateValues.text).eq("8.5204"); + expect(stateVariables["/m2a_v"].stateValues.text).eq("8.5204"); + expect(stateVariables["/m2b_v"].stateValues.text).eq("24.19"); + expect(stateVariables["/m2c_v"].stateValues.text).eq("24.19"); + expect(stateVariables["/m2d_v"].stateValues.text).eq("24.19"); + expect(stateVariables["/m2e_v"].stateValues.text).eq("24.19"); + expect(stateVariables["/m2f_v"].stateValues.text).eq("8.520385"); + expect(stateVariables["/m2g_v"].stateValues.text).eq("8.5203845"); + + expect(stateVariables["/m3"].stateValues.text).eq("1.54 * 10^(-17)"); + expect(stateVariables["/m3a"].stateValues.text).eq("1.54 * 10^(-17)"); + expect(stateVariables["/m3b"].stateValues.text).eq("0"); + expect(stateVariables["/m3c"].stateValues.text).eq("0"); + expect(stateVariables["/m3d"].stateValues.text).eq("0"); + expect(stateVariables["/m3e"].stateValues.text).eq("0"); + expect(stateVariables["/m3f"].stateValues.text).eq("1.54 * 10^(-17)"); + + expect(stateVariables["/m3_v"].stateValues.text).eq("1.54 * 10^(-17)"); + expect(stateVariables["/m3a_v"].stateValues.text).eq("1.54 * 10^(-17)"); + expect(stateVariables["/m3b_v"].stateValues.text).eq("0"); + expect(stateVariables["/m3c_v"].stateValues.text).eq("0"); + expect(stateVariables["/m3d_v"].stateValues.text).eq("0"); + expect(stateVariables["/m3e_v"].stateValues.text).eq("0"); + expect(stateVariables["/m3f_v"].stateValues.text).eq("1.54 * 10^(-17)"); + + expect(stateVariables["/m4"].stateValues.text).eq("8.00"); + expect(stateVariables["/m4a"].stateValues.text).eq("8.00"); + expect(stateVariables["/m4b"].stateValues.text).eq("16"); + expect(stateVariables["/m4c"].stateValues.text).eq("16"); + expect(stateVariables["/m4d"].stateValues.text).eq("16"); + expect(stateVariables["/m4e"].stateValues.text).eq("16"); + expect(stateVariables["/m4f"].stateValues.text).eq("8"); + + expect(stateVariables["/m4_v"].stateValues.text).eq("8.00"); + expect(stateVariables["/m4a_v"].stateValues.text).eq("8.00"); + expect(stateVariables["/m4b_v"].stateValues.text).eq("16"); + expect(stateVariables["/m4c_v"].stateValues.text).eq("16"); + expect(stateVariables["/m4d_v"].stateValues.text).eq("16"); + expect(stateVariables["/m4e_v"].stateValues.text).eq("16"); + expect(stateVariables["/m4f_v"].stateValues.text).eq("8"); + }); + + it("value on NaN", async () => { + let core = await createTestCore({ + doenetML: ` +

a

+ +

+ + $mi1 +

+ +

+ + $mi2 +

+ +

+ + +

+ +

+ + +

+ + +

+ + $mi1a +

+ +

+ + $mi2a +

+ +

+ + $mi2b +

+ +

+ + +

+ +

+ + +

+ +

+ + +

+ + +

+ 8/ + 8/ +

+ +

+ + $b>y + $b>y +

+ +

+ x>y + x>y +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi1"].stateValues.rawRendererValue).eq(""); + expect(stateVariables["/n1"].stateValues.value).eqls(NaN); + + expect(stateVariables["/mi2"].stateValues.rawRendererValue).eq(""); + expect(stateVariables["/n2"].stateValues.value).eq(3); + + expect(stateVariables["/mi3"].stateValues.rawRendererValue).eq("NaN"); + expect(stateVariables["/n3"].stateValues.value).eqls(NaN); + + expect(stateVariables["/mi4"].stateValues.rawRendererValue).eq("5"); + expect(stateVariables["/n4"].stateValues.value).eq(5); + + expect(stateVariables["/mi1a"].stateValues.rawRendererValue).eq(""); + expect(stateVariables["/n1a"].stateValues.value).eqls(NaN); + + expect(stateVariables["/mi2a"].stateValues.rawRendererValue).eq(""); + expect(stateVariables["/n2a"].stateValues.value).eq(3); + + expect(stateVariables["/mi3a"].stateValues.rawRendererValue).eq(""); + expect(stateVariables["/n3a"].stateValues.value).eqls(NaN); + + expect(stateVariables["/mi4a"].stateValues.rawRendererValue).eq("5"); + expect(stateVariables["/n4a"].stateValues.value).eq(5); + + expect(stateVariables["/mi2b"].stateValues.rawRendererValue).eq(""); + expect(stateVariables["/n2b"].stateValues.value).eq(3); + + expect(stateVariables["/mi4b"].stateValues.rawRendererValue).eq("5"); + expect(stateVariables["/n4b"].stateValues.value).eq(5); + + expect(stateVariables["/n5"].stateValues.value).eqls(NaN); + expect(stateVariables["/n6"].stateValues.value).eq(7); + + expect(stateVariables["/n7"].stateValues.value).eqls(NaN); + expect(stateVariables["/n8"].stateValues.value).eq(9); + + expect(stateVariables["/n9"].stateValues.value).eqls(NaN); + expect(stateVariables["/n10"].stateValues.value).eq(-9); + + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi3", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi4", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi1a", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi2a", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi3a", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi4a", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi2b", + core, + }); + await updateMathInputValue({ + latex: "3/4", + componentName: "/mi4b", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi1"].stateValues.rawRendererValue).eq("3/4"); + expect(stateVariables["/n1"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi2"].stateValues.rawRendererValue).eq("3/4"); + expect(stateVariables["/n2"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi3"].stateValues.rawRendererValue).eq("0.75"); + expect(stateVariables["/n3"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi4"].stateValues.rawRendererValue).eq("0.75"); + expect(stateVariables["/n4"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi1a"].stateValues.rawRendererValue).eq("3/4"); + expect(stateVariables["/n1a"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi2a"].stateValues.rawRendererValue).eq("3/4"); + expect(stateVariables["/n2a"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi3a"].stateValues.rawRendererValue).eq("0.75"); + expect(stateVariables["/n3a"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi4a"].stateValues.rawRendererValue).eq("0.75"); + expect(stateVariables["/n4a"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi2b"].stateValues.rawRendererValue).eq("3/4"); + expect(stateVariables["/n2b"].stateValues.value).eq(0.75); + + expect(stateVariables["/mi4b"].stateValues.rawRendererValue).eq("0.75"); + expect(stateVariables["/n4b"].stateValues.value).eq(0.75); + + await updateMathInputValue({ + latex: "x", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi3", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi4", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi1a", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi2a", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi3a", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi4a", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi2b", + core, + }); + await updateMathInputValue({ + latex: "x", + componentName: "/mi4b", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi1"].stateValues.rawRendererValue).eq("x"); + expect(stateVariables["/n1"].stateValues.value).eqls(NaN); + + expect(stateVariables["/mi2"].stateValues.rawRendererValue).eq("x"); + expect(stateVariables["/n2"].stateValues.value).eq(3); + + expect(stateVariables["/mi3"].stateValues.rawRendererValue).eq("NaN"); + expect(stateVariables["/n3"].stateValues.value).eqls(NaN); + + expect(stateVariables["/mi4"].stateValues.rawRendererValue).eq("5"); + expect(stateVariables["/n4"].stateValues.value).eq(5); + + expect(stateVariables["/mi1a"].stateValues.rawRendererValue).eq("x"); + expect(stateVariables["/n1a"].stateValues.value).eqls(NaN); + + expect(stateVariables["/mi2a"].stateValues.rawRendererValue).eq("x"); + expect(stateVariables["/n2a"].stateValues.value).eq(3); + + expect(stateVariables["/mi3a"].stateValues.rawRendererValue).eq(""); + expect(stateVariables["/n3a"].stateValues.value).eqls(NaN); + + expect(stateVariables["/mi4a"].stateValues.rawRendererValue).eq("5"); + expect(stateVariables["/n4a"].stateValues.value).eq(5); + + expect(stateVariables["/mi2b"].stateValues.rawRendererValue).eq("x"); + expect(stateVariables["/n2b"].stateValues.value).eq(3); + + expect(stateVariables["/mi4b"].stateValues.rawRendererValue).eq("5"); + expect(stateVariables["/n4b"].stateValues.value).eq(5); + }); + + it("indeterminate forms give NaN", async () => { + let core = await createTestCore({ + doenetML: ` +

0^0

+

Infinity^0

+

0/0

+

Infinity/Infinity

+

0*Infinity

+

Infinity-Infinity

+

1^Infinity

+

0^0^0

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/if1"].stateValues.value).eqls(NaN); + expect(stateVariables["/if2"].stateValues.value).eqls(NaN); + expect(stateVariables["/if3"].stateValues.value).eqls(NaN); + expect(stateVariables["/if4"].stateValues.value).eqls(NaN); + expect(stateVariables["/if5"].stateValues.value).eqls(NaN); + expect(stateVariables["/if6"].stateValues.value).eqls(NaN); + expect(stateVariables["/if7"].stateValues.value).eqls(NaN); + expect(stateVariables["/ifalt"].stateValues.value).eqls(NaN); + }); + + it("complex numbers", async () => { + let core = await createTestCore({ + doenetML: ` +

i

+

$i1

+

sqrt(-1)

+

exp(pi i/2)

+

$ni1^3

+

$ni2^3

+

$ni3^3

+

1/-i

+

1/$ni4

+

1/$ni5

+

1/$ni6

+

0+i

+

1i

+ +

-i

+

$ni1

+

i^3

+

(-1)^(3/2)

+

exp(3 pi i/2)

+

$i1^3

+

$i2^3

+

$i3^3

+

1/i

+

1/$i4

+

1/$i5

+

1/$i6

+

0-i

+

-1i

+ +

2+3i

+

2+3i

+

(2+3i)/(3+i)

+

2+3i/3+i

+

Infinity i

+

\\infty i

+

5+0i

+

5+0i

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/i1"].stateValues.text).eq("i"); + expect(cleanLatex(stateVariables["/i1a"].stateValues.latex)).eq("i"); + expect(stateVariables["/i2"].stateValues.text).eq("i"); + expect(stateVariables["/i3"].stateValues.text).eq("i"); + expect(stateVariables["/i4"].stateValues.text).eq("i"); + expect(stateVariables["/i5"].stateValues.text).eq("i"); + expect(stateVariables["/i6"].stateValues.text).eq("i"); + expect(stateVariables["/i7"].stateValues.text).eq("i"); + expect(stateVariables["/i8"].stateValues.text).eq("i"); + expect(stateVariables["/i9"].stateValues.text).eq("i"); + expect(stateVariables["/i10"].stateValues.text).eq("i"); + expect(stateVariables["/i11"].stateValues.text).eq("i"); + expect(stateVariables["/i12"].stateValues.text).eq("i"); + + expect(stateVariables["/ni1"].stateValues.text).eq("-i"); + expect(cleanLatex(stateVariables["/ni1a"].stateValues.latex)).eq("-i"); + expect(stateVariables["/ni2"].stateValues.text).eq("-i"); + expect(stateVariables["/ni3"].stateValues.text).eq("-i"); + expect(stateVariables["/ni4"].stateValues.text).eq("-i"); + expect(stateVariables["/ni5"].stateValues.text).eq("-i"); + expect(stateVariables["/ni6"].stateValues.text).eq("-i"); + expect(stateVariables["/ni7"].stateValues.text).eq("-i"); + expect(stateVariables["/ni8"].stateValues.text).eq("-i"); + expect(stateVariables["/ni9"].stateValues.text).eq("-i"); + expect(stateVariables["/ni10"].stateValues.text).eq("-i"); + expect(stateVariables["/ni11"].stateValues.text).eq("-i"); + expect(stateVariables["/ni12"].stateValues.text).eq("-i"); + expect(stateVariables["/ni13"].stateValues.text).eq("-i"); + + expect(stateVariables["/c1"].stateValues.text).eq("2 + 3 i"); + expect(stateVariables["/c2"].stateValues.text).eq("2 + 3 i"); + expect(stateVariables["/c3"].stateValues.text).eq("0.9 + 0.7 i"); + expect(stateVariables["/c4"].stateValues.text).eq("0.9 + 0.7 i"); + expect(stateVariables["/c5"].stateValues.text).eq("NaN + NaN i"); + expect(stateVariables["/c6"].stateValues.text).eq("NaN + NaN i"); + expect(stateVariables["/c7"].stateValues.text).eq("5"); + expect(stateVariables["/c8"].stateValues.text).eq("5"); + + expect(stateVariables["/i1"].stateValues.value).eqls({ + re: 0, + im: 1, + }); + expect(stateVariables["/i1a"].stateValues.value.tree).eqls("i"); + expect(stateVariables["/i2"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/i2"].stateValues.value.im).eq(1); + expect(stateVariables["/i3"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/i3"].stateValues.value.im).eq(1); + expect(stateVariables["/i4"].stateValues.value.re).eq(0); + expect(stateVariables["/i4"].stateValues.value.im).eq(1); + expect(stateVariables["/i5"].stateValues.value.re).eq(0); + expect(stateVariables["/i5"].stateValues.value.im).eq(1); + expect(stateVariables["/i6"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/i6"].stateValues.value.im).eq(1); + expect(stateVariables["/i7"].stateValues.value.re).eq(0); + expect(stateVariables["/i7"].stateValues.value.im).eq(1); + expect(stateVariables["/i8"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/i8"].stateValues.value.im).eq(1); + expect(stateVariables["/i9"].stateValues.value.re).eq(0); + expect(stateVariables["/i9"].stateValues.value.im).eq(1); + expect(stateVariables["/i10"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/i10"].stateValues.value.im).eq(1); + expect(stateVariables["/i11"].stateValues.value.re).eq(0); + expect(stateVariables["/i11"].stateValues.value.im).eq(1); + expect(stateVariables["/i12"].stateValues.value.re).eq(0); + expect(stateVariables["/i12"].stateValues.value.im).eq(1); + + expect(stateVariables["/ni1"].stateValues.value.re).eq(0); + expect(stateVariables["/ni1"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni1a"].stateValues.value.tree).eqls(["-", "i"]); + expect(stateVariables["/ni2"].stateValues.value.re).eq(0); + expect(stateVariables["/ni2"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni3"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/ni3"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni4"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/ni4"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni5"].stateValues.value.re).eq(0); + expect(stateVariables["/ni5"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni6"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/ni6"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni7"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/ni7"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni8"].stateValues.value.re).eq(0); + expect(stateVariables["/ni8"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni9"].stateValues.value.re).eq(0); + expect(stateVariables["/ni9"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni10"].stateValues.value.re).eq(0); + expect(stateVariables["/ni10"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni11"].stateValues.value.re).closeTo(0, 1e-14); + expect(stateVariables["/ni11"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni12"].stateValues.value.re).eq(0); + expect(stateVariables["/ni12"].stateValues.value.im).eq(-1); + expect(stateVariables["/ni13"].stateValues.value.re).eq(0); + expect(stateVariables["/ni13"].stateValues.value.im).eq(-1); + + expect(stateVariables["/c1"].stateValues.value.re).eq(2); + expect(stateVariables["/c1"].stateValues.value.im).eq(3); + expect(stateVariables["/c2"].stateValues.value.re).eq(2); + expect(stateVariables["/c2"].stateValues.value.im).eq(3); + expect(stateVariables["/c3"].stateValues.value.re).closeTo(0.9, 1e-14); + expect(stateVariables["/c3"].stateValues.value.im).closeTo(0.7, 1e-14); + expect(stateVariables["/c4"].stateValues.value.re).closeTo(0.9, 1e-14); + expect(stateVariables["/c4"].stateValues.value.im).closeTo(0.7, 1e-14); + expect(stateVariables["/c5"].stateValues.value.re).eqls(NaN); + expect(stateVariables["/c5"].stateValues.value.im).eqls(NaN); + expect(stateVariables["/c6"].stateValues.value.re).eqls(NaN); + expect(stateVariables["/c6"].stateValues.value.im).eqls(NaN); + expect(stateVariables["/c7"].stateValues.value).eq(5); + expect(stateVariables["/c8"].stateValues.value).eq(5); + }); + + it("complex numbers and inverse definition", async () => { + let core = await createTestCore({ + doenetML: ` +

1

+

1

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n1"].stateValues.value).eqls(1); + expect(stateVariables["/n2"].stateValues.value).eqls(1); + expect(stateVariables["/n3"].stateValues.value).eqls(NaN); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls(1); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls(1); + expect(stateVariables["/mi3"].stateValues.value.tree).eqls(NaN); + + await updateMathInputValue({ latex: "i", componentName: "/mi1", core }); + await updateMathInputValue({ latex: "i", componentName: "/mi2", core }); + await updateMathInputValue({ latex: "i", componentName: "/mi3", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n1"].stateValues.value).eqls({ + re: 0, + im: 1, + }); + expect(stateVariables["/n2"].stateValues.value).eqls({ + re: 0, + im: 1, + }); + expect(stateVariables["/n3"].stateValues.value).eqls({ + re: 0, + im: 1, + }); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("i"); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls("i"); + expect(stateVariables["/mi3"].stateValues.value.tree).eqls("i"); + + await updateMathInputValue({ + latex: "i+2", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "i+2", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "i+2", + componentName: "/mi3", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n1"].stateValues.value.re).eq(2); + expect(stateVariables["/n1"].stateValues.value.im).eq(1); + expect(stateVariables["/n2"].stateValues.value.re).eq(2); + expect(stateVariables["/n2"].stateValues.value.im).eq(1); + expect(stateVariables["/n3"].stateValues.value.re).eq(2); + expect(stateVariables["/n3"].stateValues.value.im).eq(1); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls([ + "+", + 2, + "i", + ]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls([ + "+", + 2, + "i", + ]); + expect(stateVariables["/mi3"].stateValues.value.tree).eqls([ + "+", + 2, + "i", + ]); + + await updateMathInputValue({ + latex: "3+0i", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "3+0i", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "3+0i", + componentName: "/mi3", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n1"].stateValues.value).eq(3); + expect(stateVariables["/n2"].stateValues.value).eq(3); + expect(stateVariables["/n3"].stateValues.value).eq(3); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls(3); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls(3); + expect(stateVariables["/mi3"].stateValues.value.tree).eqls(3); + + await updateMathInputValue({ + latex: "1i", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "1i", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "1i", + componentName: "/mi3", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n1"].stateValues.value).eqls({ + re: 0, + im: 1, + }); + expect(stateVariables["/n2"].stateValues.value).eqls({ + re: 0, + im: 1, + }); + expect(stateVariables["/n3"].stateValues.value).eqls({ + re: 0, + im: 1, + }); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls("i"); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls("i"); + expect(stateVariables["/mi3"].stateValues.value.tree).eqls("i"); + + await updateMathInputValue({ + latex: "-1i+0", + componentName: "/mi1", + core, + }); + await updateMathInputValue({ + latex: "-1i+0", + componentName: "/mi2", + core, + }); + await updateMathInputValue({ + latex: "-1i+0", + componentName: "/mi3", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n1"].stateValues.value.re).eq(0); + expect(stateVariables["/n1"].stateValues.value.im).eq(-1); + expect(stateVariables["/n2"].stateValues.value.re).eq(0); + expect(stateVariables["/n2"].stateValues.value.im).eq(-1); + expect(stateVariables["/n3"].stateValues.value.re).eq(0); + expect(stateVariables["/n3"].stateValues.value.im).eq(-1); + expect(stateVariables["/mi1"].stateValues.value.tree).eqls(["-", "i"]); + expect(stateVariables["/mi2"].stateValues.value.tree).eqls(["-", "i"]); + expect(stateVariables["/mi3"].stateValues.value.tree).eqls(["-", "i"]); + }); + + it("complex numbers, re and im", async () => { + let core = await createTestCore({ + doenetML: ` +

re(2-4i)

+

im(2-4i)

+

re((2-4i)(3-i))

+

im((2-4i)(3-i))

+

re(2-4i)

+

im(2-4i)

+

re((2-4i)(3-i))

+

im((2-4i)(3-i))

+

\\Re(2-4i)

+

\\Im(2-4i)

+

\\Re((2-4i)(3-i))

+

\\Im((2-4i)(3-i))

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n1"].stateValues.value).eq(2); + expect(stateVariables["/n2"].stateValues.value).eq(-4); + expect(stateVariables["/n3"].stateValues.value).eq(2); + expect(stateVariables["/n4"].stateValues.value).eq(-14); + expect(stateVariables["/n1a"].stateValues.value).eq(2); + expect(stateVariables["/n2a"].stateValues.value).eq(-4); + expect(stateVariables["/n3a"].stateValues.value).eq(2); + expect(stateVariables["/n4a"].stateValues.value).eq(-14); + expect(stateVariables["/n1b"].stateValues.value).eq(2); + expect(stateVariables["/n2b"].stateValues.value).eq(-4); + expect(stateVariables["/n3b"].stateValues.value).eq(2); + expect(stateVariables["/n4b"].stateValues.value).eq(-14); + }); + + it("number in graph", async () => { + let core = await createTestCore({ + doenetML: ` + + $content1 + -17 + + +

Anchor 1 coordinates:

+

Anchor 2 coordinates:

+

Change anchor 1 coordinates:

+

Change anchor 2 coordinates:

+

Position from anchor 1: $number1.positionFromAnchor

+

Position from anchor 2: $number2.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

+

Content 1: $number1

+

Content 2: $number2

+

Content 1

+

Content 2

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/number1anchor"].stateValues.latex), + ).eq("(1,3)"); + expect( + cleanLatex(stateVariables["/number2anchor"].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["/pContent1"].stateValues.text).eq( + "Content 1: 11", + ); + expect(stateVariables["/pContent2"].stateValues.text).eq( + "Content 2: -17", + ); + + // move numbers by dragging + await core.requestAction({ + actionName: "moveNumber", + componentName: "/number1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveNumber", + componentName: "/number2", + args: { x: 4, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/number1anchor"].stateValues.latex), + ).eq("(-2,3)"); + expect( + cleanLatex(stateVariables["/number2anchor"].stateValues.latex), + ).eq("(4,-5)"); + + // move numbers 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["/number1anchor"].stateValues.latex), + ).eq("(6,7)"); + expect( + cleanLatex(stateVariables["/number2anchor"].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 numbers by dragging + await core.requestAction({ + actionName: "moveNumber", + componentName: "/number1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveNumber", + componentName: "/number2", + args: { x: -8, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/number1anchor"].stateValues.latex), + ).eq("(6,7)"); + expect( + cleanLatex(stateVariables["/number2anchor"].stateValues.latex), + ).eq("(8,9)"); + + // change content of number + await updateMathInputValue({ + latex: "11+5", + componentName: "/content1", + core, + }); + await updateMathInputValue({ + latex: "-17-1", + componentName: "/content2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pContent1"].stateValues.text).eq( + "Content 1: 16", + ); + expect(stateVariables["/pContent2"].stateValues.text).eq( + "Content 2: -18", + ); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/p.test.ts b/packages/doenetml-worker/src/test/tagSpecific/p.test.ts new file mode 100644 index 000000000..39022861c --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/p.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("P tag tests", async () => { + it("two paragraphs", async () => { + let core = await createTestCore({ + doenetML: ` +

Hello, paragraph 1

+

Bye, paragraph 2

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("Hello, paragraph 1"); + expect(stateVariables["/p2"].stateValues.text).eq("Bye, paragraph 2"); + }); + + it("paragraph with math", async () => { + let core = await createTestCore({ + doenetML: ` +

math in paragraph: x+x

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.text).eq( + "math in paragraph: 2 x", + ); + }); + + it("spaces preserved between tags", async () => { + let core = await createTestCore({ + doenetML: ` +

Hello x

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.text).eq("Hello x"); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/polygon.test.ts b/packages/doenetml-worker/src/test/tagSpecific/polygon.test.ts new file mode 100644 index 000000000..5ecfa9c07 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/polygon.test.ts @@ -0,0 +1,6719 @@ +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); + +async function testPolygonCopiedTwice({ + core, + vertices, + polygonName = "/pg", + graph1Name = "/g1", + graph2Name = "/g2", + graph3Name = "/g3", +}: { + core: any; + vertices: (number | string)[][]; + polygonName?: string; + graph1Name?: string; + graph2Name?: string; + graph3Name?: string; +}) { + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables[graph1Name + polygonName].stateValues.numVertices, + ).eqls(vertices.length); + expect( + stateVariables[graph2Name + polygonName].stateValues.numVertices, + ).eqls(vertices.length); + expect( + stateVariables[graph3Name + polygonName].stateValues.numVertices, + ).eqls(vertices.length); + + for (let i in vertices) { + if ( + typeof vertices[i][0] === "number" && + Number.isFinite(vertices[i][0]) + ) { + expect( + me + .fromAst( + stateVariables[graph1Name + polygonName].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + expect( + me + .fromAst( + stateVariables[graph2Name + polygonName].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + expect( + me + .fromAst( + stateVariables[graph3Name + polygonName].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + } else { + expect( + stateVariables[graph1Name + polygonName].stateValues.vertices[ + i + ][0].tree, + ).eq(vertices[i][0]); + expect( + stateVariables[graph2Name + polygonName].stateValues.vertices[ + i + ][0].tree, + ).eq(vertices[i][0]); + expect( + stateVariables[graph3Name + polygonName].stateValues.vertices[ + i + ][0].tree, + ).eq(vertices[i][0]); + } + if ( + typeof vertices[i][1] === "number" && + Number.isFinite(vertices[i][1]) + ) { + expect( + me + .fromAst( + stateVariables[graph1Name + polygonName].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + expect( + me + .fromAst( + stateVariables[graph2Name + polygonName].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + expect( + me + .fromAst( + stateVariables[graph3Name + polygonName].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + } else { + expect( + stateVariables[graph1Name + polygonName].stateValues.vertices[ + i + ][1].tree, + ).eq(vertices[i][1]); + expect( + stateVariables[graph2Name + polygonName].stateValues.vertices[ + i + ][1].tree, + ).eq(vertices[i][1]); + expect( + stateVariables[graph3Name + polygonName].stateValues.vertices[ + i + ][1].tree, + ).eq(vertices[i][1]); + } + } +} + +describe("Polygon tag tests", async () => { + it("Polygon vertices and copied points", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,5) + (-4,-1) + (5,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 5], + [-4, -1], + [5, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ core, vertices }); + + // move individual vertex + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // move copied polygon up and to the right + let moveX = 3; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // move double copied individual vertex + vertices[2] = [-9, -8]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: vertices[2] }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + }); + + it("Polygon macro in vertices", async () => { + let core = await createTestCore({ + doenetML: ` + -1 + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 5], + [-4, -1], + [5, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ core, vertices }); + + // move individual vertex + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // move copied polygon up and to the right + let moveX = 3; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // move double copied individual vertex + vertices[2] = [-9, -8]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: vertices[2] }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + }); + + it("dynamic polygon with vertices from copied map, initially zero, copied", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices: number[][] = []; + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "1", + componentName: "/length", + core, + }); + vertices[0] = [0, 5 * Math.sin(0)]; + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "2", + componentName: "/length", + core, + }); + vertices[1] = [1, 5 * Math.sin(1)]; + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "3", + componentName: "/length", + core, + }); + vertices[2] = [2, 5 * Math.sin(2)]; + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "2", + componentName: "/length", + core, + }); + vertices.splice(2, 1); + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "0", + componentName: "/length", + core, + }); + vertices = []; + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "5", + componentName: "/length", + core, + }); + for (let i = 0; i < 5; i++) { + vertices.push([i, 5 * Math.sin(i)]); + } + await testPolygonCopiedTwice({ core, vertices }); + + // start over and begin with big increment + core = await createTestCore({ + doenetML: ` + + + + + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + vertices = []; + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "10", + componentName: "/length", + core, + }); + for (let i = 0; i < 10; i++) { + vertices.push([i, 5 * Math.sin(i)]); + } + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "1", + componentName: "/length", + core, + }); + vertices = [[0, 5 * Math.sin(0)]]; + await testPolygonCopiedTwice({ core, vertices }); + }); + + it("polygon with initially undefined point", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [1, 2], + [-1, 5], + ["\uff3f", 7], + [3, -5], + [-4, -3], + ]; + await testPolygonCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "-2", + componentName: "/mi", + core, + }); + + vertices[2][0] = -2; + await testPolygonCopiedTwice({ core, vertices }); + }); + + it(`can't move polygon based on map`, async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices: number[][] = []; + for (let i = -5; i <= 5; i++) { + vertices.push([i, 5 * Math.sin(i)]); + } + await testPolygonCopiedTwice({ core, vertices }); + + // can't move points + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/mp1", + args: { x: 9, y: -8 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/mp9", + args: { x: -8, y: 4 }, + event: null, + }); + + // can't move polygon1 + let moveX = 3; + let moveY = 2; + + let vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // can't move polygon2 + moveX = -5; + moveY = 6; + + vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // can't move polygon3 + moveX = 7; + moveY = -4; + + vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + }); + + it(`create moveable polygon based on map`, async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices: number[][] = []; + for (let i = -5; i <= 5; i++) { + vertices.push([i, 5 * Math.sin(i)]); + } + await testPolygonCopiedTwice({ core, vertices }); + + // can move points + + vertices[0] = [9, -8]; + vertices[8] = [-8, 4]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/mp1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/mp9", + args: { x: vertices[8][0], y: vertices[8][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // can move polygon1 + let moveX = 3; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // can move polygon2 + moveX = -5; + moveY = 6; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + moveX = 7; + moveY = -4; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + }); + + it("copy vertices of polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $pl.vertex1{assignNames="v1"} + $pl.vertex2{assignNames="v2"} + $pl.vertex3{assignNames="v3"} + $pl.vertex4{assignNames="v4"} + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let ps = [ + [-3, -1], + [1, 2], + [3, 4], + [6, -2], + ]; + + for (let i = 0; i < 4; i++) { + expect(stateVariables[`/v${i + 1}`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + } + + // move individually copied vertices + ps = [ + [-5, 3], + [-2, 7], + [0, -8], + [9, -6], + ]; + + for (let i = 0; i < 4; i++) { + await core.requestAction({ + actionName: "movePoint", + componentName: `/v${i + 1}`, + args: { x: ps[i][0], y: ps[i][1] }, + event: null, + }); + } + + stateVariables = await returnAllStateVariables(core); + for (let i = 0; i < 4; i++) { + expect(stateVariables[`/v${i + 1}`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + } + + // move array-copied vertices + ps = [ + [-7, -1], + [-3, 5], + [2, 4], + [6, 0], + ]; + + for (let i = 0; i < 4; i++) { + await core.requestAction({ + actionName: "movePoint", + componentName: `/v${i + 1}a`, + args: { x: ps[i][0], y: ps[i][1] }, + event: null, + }); + } + + stateVariables = await returnAllStateVariables(core); + for (let i = 0; i < 4; i++) { + expect(stateVariables[`/v${i + 1}`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + } + }); + + it("new polygon from copied vertices of polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + $g2{name="g3"} + `, + }); + + let vertices = [ + [-9, 6], + [-3, 7], + [4, 0], + [8, 5], + ]; + + await testPolygonCopiedTwice({ core, vertices }); + + // move first polygon up and to the right + let moveX = 4; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // move copied polygon up and to the left + moveX = -7; + moveY = 3; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // move double copied polygon down and to the left + moveX = -1; + moveY = -4; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + }); + + it("new polygon as translated version of polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + $_polygon1.vertices{name="vs"} + + + + + $_polygon2.vertices{assignNames="p1 p2 p3 p4"} + + `, + }); + + async function testPolygons({ vertices, transX, transY }) { + let vertices2 = vertices.map((v) => [v[0] + transX, v[1] + transY]); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_polygon1"].stateValues.numVertices).eqls( + vertices.length, + ); + expect(stateVariables["/_polygon2"].stateValues.numVertices).eqls( + vertices.length, + ); + + for (let i in vertices) { + if (Number.isFinite(vertices[i][0])) { + expect( + me + .fromAst( + stateVariables["/_polygon1"].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + expect( + me + .fromAst( + stateVariables["/_polygon2"].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices2[i][0], 1e-12); + } else { + expect( + stateVariables["/_polygon1"].stateValues.vertices[i][0] + .tree, + ).eq(vertices[i][0]); + expect( + stateVariables["/_polygon2"].stateValues.vertices[i][0] + .tree, + ).eq(vertices2[i][0]); + } + if (Number.isFinite(vertices[i][1])) { + expect( + me + .fromAst( + stateVariables["/_polygon1"].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + expect( + me + .fromAst( + stateVariables["/_polygon2"].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices2[i][1], 1e-12); + } else { + expect( + stateVariables["/_polygon1"].stateValues.vertices[i][1] + .tree, + ).eq(vertices[i][1]); + expect( + stateVariables["/_polygon2"].stateValues.vertices[i][1] + .tree, + ).eq(vertices2[i][1]); + } + } + } + + let vertices = [ + [0, 0], + [3, -4], + [1, -6], + [-5, -6], + ]; + let transX = 5; + let transY = 7; + + await testPolygons({ vertices, transX, transY }); + + // move points on first polygon + vertices = [ + [1, -1], + [-3, 2], + [-1, 7], + [6, 3], + ]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygons({ vertices, transX, transY }); + + // move points on second polygon + let vertices2 = [ + [-3, 4], + [1, 0], + [9, 6], + [2, -1], + ]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon2", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + vertices = vertices2.map((v) => [v[0] - transX, v[1] - transY]); + + await testPolygons({ vertices, transX, transY }); + + // change translation + await updateMathInputValue({ + latex: "2", + componentName: "/transx", + core, + }); + await updateMathInputValue({ + latex: "10", + componentName: "/transy", + core, + }); + + transX = 2; + transY = 10; + + await testPolygons({ vertices, transX, transY }); + }); + + it("parallelogram based on three points", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + let D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move first vertex + A = [-4, -1]; + D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/parallelogram", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + B = [8, 9]; + D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/parallelogram", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move third vertex + C = [-3, 7]; + D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/parallelogram", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move fourth vertex + D = [7, 0]; + B = [A[0] + C[0] - D[0], A[1] + C[1] - D[1]]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/parallelogram", + args: { + pointCoords: { 3: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + }); + + it("new polygon from copied vertices, some flipped", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + `, + }); + + async function testPolygons({ vertices }) { + let vertices2 = [...vertices]; + vertices2[1] = [vertices2[1][1], vertices2[1][0]]; + vertices2[3] = [vertices2[3][1], vertices2[3][0]]; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_polygon1"].stateValues.numVertices).eqls( + vertices.length, + ); + expect(stateVariables["/_polygon2"].stateValues.numVertices).eqls( + vertices.length, + ); + + for (let i in vertices) { + if (Number.isFinite(vertices[i][0])) { + expect( + me + .fromAst( + stateVariables["/_polygon1"].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + expect( + me + .fromAst( + stateVariables["/_polygon2"].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices2[i][0], 1e-12); + } else { + expect( + stateVariables["/_polygon1"].stateValues.vertices[i][0] + .tree, + ).eq(vertices[i][0]); + expect( + stateVariables["/_polygon2"].stateValues.vertices[i][0] + .tree, + ).eq(vertices2[i][0]); + } + if (Number.isFinite(vertices[i][1])) { + expect( + me + .fromAst( + stateVariables["/_polygon1"].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + expect( + me + .fromAst( + stateVariables["/_polygon2"].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices2[i][1], 1e-12); + } else { + expect( + stateVariables["/_polygon1"].stateValues.vertices[i][1] + .tree, + ).eq(vertices[i][1]); + expect( + stateVariables["/_polygon2"].stateValues.vertices[i][1] + .tree, + ).eq(vertices2[i][1]); + } + } + } + + let vertices = [ + [-9, 6], + [-3, 7], + [4, 0], + [8, 5], + ]; + + await testPolygons({ vertices }); + + // move first polygon vertices + vertices = [ + [7, 2], + [1, -3], + [2, 9], + [-4, -3], + ]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolygons({ vertices }); + + // move second polygon vertices + let vertices2 = [ + [-1, 9], + [5, 7], + [-8, 1], + [-7, 6], + ]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon2", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + vertices = [...vertices2]; + vertices[1] = [vertices[1][1], vertices[1][0]]; + vertices[3] = [vertices[3][1], vertices[3][0]]; + + await testPolygons({ vertices }); + }); + + it("four vertex polygon based on three points", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + let D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move first vertex + A = [-4, -1]; + D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move second vertex + B = [8, 9]; + D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move third vertex + C = [-3, 7]; + D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move fourth vertex + D = [7, 0]; + A = [C[0] + B[0] - D[0], C[1] + B[1] - D[1]]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 3: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + }); + + it("fourth vertex depends on internal copy of first vertex", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_polygon1"].stateValues.numVertices).eq(4); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move first vertex + A = [-4, -1]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move fourth vertex + A = [7, 0]; + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 3: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + }); + + it("first vertex depends on internal copy of fourth vertex", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_polygon1"].stateValues.numVertices).eq(4); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move first vertex + A = [-4, -1]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move fourth vertex + A = [7, 0]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 3: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + }); + + it("first vertex depends fourth, formula for fifth", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + + $_polygon1.vertices{assignNames="p1 p2 p3 p4 p5"} + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + let D = [A[0] + 1, 2]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move first vertex + A = [-4, -1]; + D[0] = A[0] + 1; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move fourth vertex + A = [7, 0]; + D[0] = A[0] + 1; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 3: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move fifth vertex + D = [-5, 9]; + A[0] = D[0] - 1; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 4: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polygon1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polygon1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polygon1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polygon1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + }); + + it("first, fourth, seventh vertex depends on fourth, seventh, tenth", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let A = [-5, -1]; + let B = [1, 2]; + let C = [3, 4]; + let D = [5, 7]; + let E = [-5, 7]; + let F = [3, 1]; + let G = [5, 0]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move first vertex + A = [-4, -9]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move fourth vertex + A = [7, 0]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 3: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move fifth vertex + D = [-9, 1]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 4: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move sixth vertex + E = [-3, 6]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 5: E }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move seventh vertex + A = [2, -4]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 6: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move eighth vertex + F = [6, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 7: F }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move ninth vertex + G = [1, -8]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 8: G }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move tenth vertex + A = [-6, 10]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 9: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + }); + + it("first, fourth, seventh vertex depends on shifted fourth, seventh, tenth", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + + $P.vertices{assignNames="p1 p2 p3 p4 p5 p6 p7 p8 p9 p10"} + + `, + }); + + let A = [-5, -1]; + let B = [1, 2]; + let C = [3, 4]; + let D = [5, 7]; + let E = [-5, 7]; + let F = [3, 1]; + let G = [5, 0]; + let A1 = [A[0] + 1, A[1] + 1]; + let A2 = [A[0] + 2, A[1] + 2]; + let A3 = [A[0] + 3, A[1] + 3]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move first vertex + A = [-4, -9]; + A1 = [A[0] + 1, A[1] + 1]; + A2 = [A[0] + 2, A[1] + 2]; + A3 = [A[0] + 3, A[1] + 3]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 0: A3 }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move fourth vertex + A = [7, 0]; + A1 = [A[0] + 1, A[1] + 1]; + A2 = [A[0] + 2, A[1] + 2]; + A3 = [A[0] + 3, A[1] + 3]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 3: A2 }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move fifth vertex + D = [-9, 1]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 4: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move sixth vertex + E = [-3, 6]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 5: E }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move seventh vertex + A = [2, -4]; + A1 = [A[0] + 1, A[1] + 1]; + A2 = [A[0] + 2, A[1] + 2]; + A3 = [A[0] + 3, A[1] + 3]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 6: A1 }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move eighth vertex + F = [6, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 7: F }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move ninth vertex + G = [1, -8]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 8: G }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move tenth vertex + A = [-6, 7]; + A1 = [A[0] + 1, A[1] + 1]; + A2 = [A[0] + 2, A[1] + 2]; + A3 = [A[0] + 3, A[1] + 3]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/P", + args: { + pointCoords: { 9: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + }); + + it("attract to polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $_polygon1 + + + + `, + }); + + let x1 = 3, + x2 = -4, + x3 = 5; + let y1 = 5, + y2 = -1, + y3 = 2; + + // point originally not attracted + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_point1"].stateValues.coords.tree).eqls([ + "vector", + 7, + 8, + ]); + + // move point near segment 1 + let x = 1; + let mseg1 = (y2 - y1) / (x2 - x1); + let y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + let px = stateVariables["/_point1"].stateValues.xs[0].tree; + let py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move point near segment 2 + x = 3; + let mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.4; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + + // move point near segment between first and last vertices + x = 4; + let mseg3 = (y1 - y3) / (x1 - x3); + y = mseg3 * (x - x3) + y3 + 0.2; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); + + // move point just past first vertex + x = x1 + 0.2; + y = y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x1, 1e-6); + expect(py).closeTo(y1, 1e-6); + + // point not attracted along extension of first segment + x = 4; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + x = -5; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + // move point just past second vertex + x = x2 - 0.2; + y = y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // point not attracted along extension of second segment + x = 6; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + x = -5; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + // move polygon so point attracts to first segment + let moveX = -3; + let moveY = -2; + + x1 += moveX; + x2 += moveX; + x3 += moveX; + y1 += moveY; + y2 += moveY; + y3 += moveY; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: [ + [x1, y1], + [x2, y2], + [x3, y3], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg1 = (y2 - y1) / (x2 - x1); + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move second vertex so point attracts to second segment + moveX = -1; + moveY = 1; + + x2 += moveX; + y2 += moveY; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 1: [x2, y2] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg2 = (y2 - y3) / (x2 - x3); + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + }); + + it("constrain to polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $_polygon1 + + + + `, + }); + + let x1 = 3, + x2 = -4, + x3 = 5; + let y1 = 5, + y2 = -1, + y3 = 2; + + // point originally constrained + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_point1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + + // move point near segment 1 + let x = 1; + let mseg1 = (y2 - y1) / (x2 - x1); + let y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + let px = stateVariables["/_point1"].stateValues.xs[0].tree; + let py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move point near segment 2 + x = 3; + let mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.4; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + + // move point near segment between first and last vertices + + x = 4; + let mseg3 = (y1 - y3) / (x1 - x3); + y = mseg3 * (x - x3) + y3 + 0.2; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); + + // move point just past first vertex + + x = x1 + 0.2; + y = y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x1, 1e-6); + expect(py).closeTo(y1, 1e-6); + + //point along extension of first segment constrained to endpoint + + x = 4; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x1, 1e-6); + expect(py).closeTo(y1, 1e-6); + x = -5; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // move point just past second vertex + + x = x2 - 0.2; + y = y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + //point along extension of second segment constrained to endpoint + + x = 6; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x3, 1e-6); + expect(py).closeTo(y3, 1e-6); + + x = -5; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // move polygon so point constrained to first segment + + let moveX = -3; + let moveY = -5; + + x1 += moveX; + x2 += moveX; + x3 += moveX; + y1 += moveY; + y2 += moveY; + y3 += moveY; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: [ + [x1, y1], + [x2, y2], + [x3, y3], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg1 = (y2 - y1) / (x2 - x1); + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move second vertex so point constrained to second segment + + moveX = -1; + moveY = 8; + + x2 += moveX; + y2 += moveY; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 1: [x2, y2] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg2 = (y2 - y3) / (x2 - x3); + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + }); + + it("constrain to polygon, different scales from graph", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $p + + + + `, + }); + + let x1 = -50, + x2 = -40, + x3 = 70, + x4 = 10; + let y1 = -0.02, + y2 = 0.07, + y3 = 0.06, + y4 = -0.01; + + // point originally on segment 3 + + let stateVariables = await returnAllStateVariables(core); + + let mseg3 = (y4 - y3) / (x4 - x3); + + let px = stateVariables["/A"].stateValues.xs[0].tree; + let py = stateVariables["/A"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); + + // move point near segment 1 + + let mseg1 = (y2 - y1) / (x2 - x1); + + await core.requestAction({ + actionName: "movePoint", + componentName: `/A`, + args: { x: -20, y: 0.02 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/A"].stateValues.xs[0].tree; + py = stateVariables["/A"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move point near segment 2 + + let mseg2 = (y2 - y3) / (x2 - x3); + + await core.requestAction({ + actionName: "movePoint", + componentName: `/A`, + args: { x: 0, y: 0.04 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/A"].stateValues.xs[0].tree; + py = stateVariables["/A"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + + // move point near segment 4 + + let mseg4 = (y4 - y1) / (x4 - x1); + + await core.requestAction({ + actionName: "movePoint", + componentName: `/A`, + args: { x: -10, y: 0.02 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/A"].stateValues.xs[0].tree; + py = stateVariables["/A"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg4 * (px - x4) + y4, 1e-6); + }); + + it("constrain to interior of polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $_polygon1 + + + + `, + }); + + let x1 = 3, + x2 = -4, + x3 = 5; + let y1 = 5, + y2 = -1, + y3 = 2; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_point1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + + // move point near segment 1, outside polygon + + let x = 1; + let mseg1 = (y2 - y1) / (x2 - x1); + let y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + let px = stateVariables["/_point1"].stateValues.xs[0].tree; + let py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move point near segment 2, but inside polygon + + x = 3; + y = 1.5; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(3, 1e-12); + expect(py).closeTo(1.5, 1e-12); + + // move point near segment between first and last vertices, but outside polygon + + x = 4; + let mseg3 = (y1 - y3) / (x1 - x3); + y = mseg3 * (x - x3) + y3 + 0.2; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); + + // move point just past first vertex + + x = x1 + 0.2; + y = y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x1, 1e-6); + expect(py).closeTo(y1, 1e-6); + + // point along extension of first segment constrained to endpoint + + x = 4; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x1, 1e-6); + expect(py).closeTo(y1, 1e-6); + + x = -5; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // move point just past second vertex + + x = x2 - 0.2; + y = y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // point along extension of second segment constrained to endpoint + + x = 6; + let mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x3, 1e-6); + expect(py).closeTo(y3, 1e-6); + + // repeat for other side of second segment + let xsave, ysave; + + x = -5; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // save point coordinates, as is last time move point + xsave = x2; + ysave = y2; + + // move polygon so point constrained to first segment + + let moveX = -3; + let moveY = -5; + + x1 += moveX; + x2 += moveX; + x3 += moveX; + y1 += moveY; + y2 += moveY; + y3 += moveY; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: [ + [x1, y1], + [x2, y2], + [x3, y3], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg1 = (y2 - y1) / (x2 - x1); + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move second vertex so point constrained to second segment + + moveX = -1; + moveY = 8; + + x2 += moveX; + y2 += moveY; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 1: [x2, y2] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg2 = (y2 - y3) / (x2 - x3); + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + + // move third vertex so point is in interior + + x3 = -4; + y3 = -6; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/_polygon1", + args: { + pointCoords: { 2: [x3, y3] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + // point moves to coordinates where last moved the point + expect(px).closeTo(xsave, 1e-6); + expect(py).closeTo(ysave, 1e-6); + }); + + it("constrain to interior of non-simple polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $pg + + + + `, + }); + + // point originally in interior + + let stateVariables = await returnAllStateVariables(core); + let px = stateVariables["/P"].stateValues.xs[0].tree; + let py = stateVariables["/P"].stateValues.xs[1].tree; + expect(px).closeTo(7, 1e-12); + expect(py).closeTo(6, 1e-12); + + // move point above polygon + + await core.requestAction({ + actionName: "movePoint", + componentName: `/P`, + args: { x: 3, y: 10 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + px = stateVariables["/P"].stateValues.xs[0].tree; + py = stateVariables["/P"].stateValues.xs[1].tree; + expect(px).closeTo(3, 1e-12); + expect(py).closeTo(8, 1e-12); + + // move point inside doubly wound region + + await core.requestAction({ + actionName: "movePoint", + componentName: `/P`, + args: { x: 3, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/P"].stateValues.xs[0].tree; + py = stateVariables["/P"].stateValues.xs[1].tree; + expect(px).closeTo(3, 1e-12); + expect(py).closeTo(5, 1e-12); + + // attempt to move point inside zero wound region + + await core.requestAction({ + actionName: "movePoint", + componentName: `/P`, + args: { x: 4.9, y: 3 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/P"].stateValues.xs[0].tree; + py = stateVariables["/P"].stateValues.xs[1].tree; + expect(px).closeTo(4, 1e-12); + expect(py).closeTo(3, 1e-12); + }); + + it("fixed polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.fixed).eq(true); + + // cannot move vertices + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: [ + [4, 7], + [8, 10], + [1, 9], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + }); + + it("copy propIndex of vertices, dot and array notation", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + + +

+ +

$pl.vertices[$n]{assignNames="P1 P2 P3"}

+ +

$pl.vertex2[$n]{assignNames="x"}

+ +

$pl.vertices[2][$n]{assignNames="xa"}

+ `, + }); + + let t1x = 2, + t1y = -3; + let t2x = 3, + t2y = 4; + let t3x = -3, + t3y = 4; + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"]).eq(undefined); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"]).eq(undefined); + expect(stateVariables["/xa"]).eq(undefined); + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + t1x, + t1y, + ]); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"].stateValues.value.tree).eq(t2x); + expect(stateVariables["/xa"].stateValues.value.tree).eq(t2x); + + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + t2x, + t2y, + ]); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"].stateValues.value.tree).eq(t2y); + expect(stateVariables["/xa"].stateValues.value.tree).eq(t2y); + + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + t3x, + t3y, + ]); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"]).eq(undefined); + expect(stateVariables["/xa"]).eq(undefined); + + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"]).eq(undefined); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"]).eq(undefined); + expect(stateVariables["/xa"]).eq(undefined); + }); + + it("polygon from vector operations", async () => { + let core = await createTestCore({ + doenetML: ` + (-3,2) + + (2,1) + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polygon"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [7, -2], + [6, 3], + [-4, 5], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/polygon", + args: { + pointCoords: { 0: [3, 5] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polygon"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [6, 3], + [-4, 5], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/polygon", + args: { + pointCoords: { 1: [-9, -6] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polygon"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [-9, -6], + [-9, 2], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/polygon", + args: { + pointCoords: { 2: [-3, 1] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polygon"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [9, -9], + [-3, 1], + ]); + }); + + it("polygon from vector operations, create individual vectors", async () => { + let core = await createTestCore({ + doenetML: ` + (-3,2) + + (2,1) + + 2(2,-3)+(3,4) + 3$P + $P+2$m + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polygon"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [7, -2], + [6, 3], + [-4, 5], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/polygon", + args: { + pointCoords: { 0: [3, 5] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polygon"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [6, 3], + [-4, 5], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/polygon", + args: { + pointCoords: { 1: [-9, -6] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polygon"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [-9, -6], + [-9, 2], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/polygon", + args: { + pointCoords: { 2: [-3, 1] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polygon"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [9, -9], + [-3, 1], + ]); + }); + + it("changing styles", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + + + + + + + + + + + + + + + + + + + + + +

First polygon is $p1.styleDescription{assignNames="st1"}. It is a $p1.styleDescriptionWithNoun{assignNames="stn1"}. + Its border is $p1.borderStyleDescription{assignNames="bst1"}. Its fill is $p1.fillStyleDescription{assignNames="fst1"}. +

+

Second polygon is $p2.styleDescription{assignNames="st2"}. It is a $p2.styleDescriptionWithNoun{assignNames="stn2"}. + Its border is $p2.borderStyleDescription{assignNames="bst2"}. Its fill is $p2.fillStyleDescription{assignNames="fst2"}. +

+

Third polygon is $p3.styleDescription{assignNames="st3"}. It is a $p3.styleDescriptionWithNoun{assignNames="stn3"}. + Its border is $p3.borderStyleDescription{assignNames="bst3"}. Its fill is $p3.fillStyleDescription{assignNames="fst3"}. +

+

Fourth polygon is $p4.styleDescription{assignNames="st4"}. It is a $p4.styleDescriptionWithNoun{assignNames="stn4"}. + Its border is $p4.borderStyleDescription{assignNames="bst4"}. Its fill is $p4.fillStyleDescription{assignNames="fst4"}. +

+ +

Fifth polygon is $p5.styleDescription{assignNames="st5"}. It is a $p5.styleDescriptionWithNoun{assignNames="stn5"}. + Its border is $p5.borderStyleDescription{assignNames="bst5"}. Its fill is $p5.fillStyleDescription{assignNames="fst5"}. +

+

Sixth polygon is $p6.styleDescription{assignNames="st6"}. It is a $p6.styleDescriptionWithNoun{assignNames="stn6"}. + Its border is $p6.borderStyleDescription{assignNames="bst6"}. Its fill is $p6.fillStyleDescription{assignNames="fst6"}. +

+

Seventh polygon is $p7.styleDescription{assignNames="st7"}. It is a $p7.styleDescriptionWithNoun{assignNames="stn7"}. + Its border is $p7.borderStyleDescription{assignNames="bst7"}. Its fill is $p7.fillStyleDescription{assignNames="fst7"}. +

+

Eighth polygon is $p8.styleDescription{assignNames="st8"}. It is a $p8.styleDescriptionWithNoun{assignNames="stn8"}. + Its border is $p8.borderStyleDescription{assignNames="bst8"}. Its fill is $p8.fillStyleDescription{assignNames="fst8"}. +

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/st1"].stateValues.text).eq("blue"); + expect(stateVariables["/stn1"].stateValues.text).eq("blue polygon"); + expect(stateVariables["/bst1"].stateValues.text).eq("blue"); + expect(stateVariables["/fst1"].stateValues.text).eq("unfilled"); + + expect(stateVariables["/st2"].stateValues.text).eq("filled blue"); + expect(stateVariables["/stn2"].stateValues.text).eq( + "filled blue polygon", + ); + expect(stateVariables["/bst2"].stateValues.text).eq("blue"); + expect(stateVariables["/fst2"].stateValues.text).eq("blue"); + + expect(stateVariables["/st3"].stateValues.text).eq("red"); + expect(stateVariables["/stn3"].stateValues.text).eq("red polygon"); + expect(stateVariables["/bst3"].stateValues.text).eq("red"); + expect(stateVariables["/fst3"].stateValues.text).eq("unfilled"); + + expect(stateVariables["/st4"].stateValues.text).eq( + "filled green with red border", + ); + expect(stateVariables["/stn4"].stateValues.text).eq( + "filled green polygon with a red border", + ); + expect(stateVariables["/bst4"].stateValues.text).eq("red"); + expect(stateVariables["/fst4"].stateValues.text).eq("green"); + + expect(stateVariables["/st5"].stateValues.text).eq("thick blue"); + expect(stateVariables["/stn5"].stateValues.text).eq( + "thick blue polygon", + ); + expect(stateVariables["/bst5"].stateValues.text).eq("thick blue"); + expect(stateVariables["/fst5"].stateValues.text).eq("unfilled"); + + expect(stateVariables["/st6"].stateValues.text).eq( + "filled blue with thick border", + ); + expect(stateVariables["/stn6"].stateValues.text).eq( + "filled blue polygon with a thick border", + ); + expect(stateVariables["/bst6"].stateValues.text).eq("thick blue"); + expect(stateVariables["/fst6"].stateValues.text).eq("blue"); + + expect(stateVariables["/st7"].stateValues.text).eq("thin dotted red"); + expect(stateVariables["/stn7"].stateValues.text).eq( + "thin dotted red polygon", + ); + expect(stateVariables["/bst7"].stateValues.text).eq("thin dotted red"); + expect(stateVariables["/fst7"].stateValues.text).eq("unfilled"); + + expect(stateVariables["/st8"].stateValues.text).eq( + "filled green with thin dotted red border", + ); + expect(stateVariables["/stn8"].stateValues.text).eq( + "filled green polygon with a thin dotted red border", + ); + expect(stateVariables["/bst8"].stateValues.text).eq("thin dotted red"); + expect(stateVariables["/fst8"].stateValues.text).eq("green"); + }); + + it("draggable, vertices draggable", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

draggable:

+

vertices draggable:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + + // cannot move single vertex + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: { 0: [4, 7] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + + // cannot move all vertices + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: [ + [4, 7], + [8, 10], + [1, 9], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + + // only vertices draggable + + await updateBooleanInputValue({ + boolean: true, + componentName: "/verticesDraggable", + core, + }); + + // can move single vertex + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: { 0: [4, 7] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([4, 7]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); + + // cannot move all vertices + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: [ + [3, 8], + [8, 10], + [1, 9], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([4, 7]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); + + // vertices and polygon draggable + + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable", + core, + }); + + // can move single vertex + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: { 1: [-3, 2] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([4, 7]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([-3, 2]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(true); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); + + // can move all vertices + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: [ + [3, 8], + [8, 10], + [1, 9], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([3, 8]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([8, 10]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([1, 9]); + expect(stateVariables["/p"].stateValues.draggable).eq(true); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); + + // polygon but not vertices draggable + + await updateBooleanInputValue({ + boolean: false, + componentName: "/verticesDraggable", + core, + }); + + // cannot move single vertex + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: { 2: [9, 3] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([3, 8]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([8, 10]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([1, 9]); + expect(stateVariables["/p"].stateValues.draggable).eq(true); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + + // can move all vertices + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: [ + [-4, 1], + [9, -4], + [0, 7], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([-4, 1]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([9, -4]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([0, 7]); + expect(stateVariables["/p"].stateValues.draggable).eq(true); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + }); + + it("One vertex constrained to grid", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,5) + (-4,-1) + (5,2) + + + + + (-3,4) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 5], + [-4, -1], + [6, 4], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ core, vertices }); + + // move individual vertex + + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // move copied polygon up and to the right + + let moveX = 4; + let moveY = 3; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = 1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolygonCopiedTwice({ core, vertices }); + + // try to move double copied polygon down and to the right + + moveX = 1; + moveY = -7; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = -1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolygonCopiedTwice({ core, vertices }); + }); + + it("Two vertices constrained to same grid", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,5) + + + + + (-4,-1) + (5,2) + + + + + (-3,4) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 4], + [-4, -1], + [6, 4], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ core, vertices }); + + // move individual vertex + + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ core, vertices }); + + // move copied polygon up and to the right + + let moveX = 4; + let moveY = 3; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = 1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolygonCopiedTwice({ core, vertices }); + + // try to move double copied polygon down and to the right + + moveX = 1; + moveY = -7; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = -1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolygonCopiedTwice({ core, vertices }); + }); + + it("Three vertices constrained to same grid", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,5) + + + + + (-4,-1) + + + + + (5,2) + + + + + (-3,4) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 4], + [-3, 0], + [6, 4], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ core, vertices }); + + // move individual vertex + + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + // adjust for constraint + vertices[1] = [3, 8]; + + await testPolygonCopiedTwice({ core, vertices }); + + // move copied polygon up and to the right + + let moveX = 4; + let moveY = 3; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = 1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolygonCopiedTwice({ core, vertices }); + + // try to move double copied polygon down and to the right + + moveX = 1; + moveY = -7; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = -1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolygonCopiedTwice({ core, vertices }); + }); + + it("Two vertices fixed, handle rounding error from third calculated vertex", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + (-1,-1) + (5,2) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + + `, + }); + + let vertices = [ + [1, 2], + [-3, -3], + [5, 2], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // try to move polygon where calculated vertex can't be represented exactly + + // key point: (desiredVertex2X/3)*3 !== desiredVertex2X due to round off error + let desiredVertex2X = 0.38823529411764707; + let desiredVertex2Y = -2.7803926355698527; + + let moveX = desiredVertex2X - vertices[1][0]; + let moveY = desiredVertex2Y - vertices[1][1]; + + let desiredVertices: number[][] = []; + + for (let i = 0; i < vertices.length; i++) { + if (i === 1) { + desiredVertices.push([desiredVertex2X, desiredVertex2Y]); + } else { + desiredVertices.push([ + vertices[i][0] + moveX, + vertices[i][1] + moveY, + ]); + } + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: desiredVertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("handle bad vertices", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + // document is created + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pl"]).not.eq(undefined); + }); + + it("area and perimeter", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

Area:

+

Perimeter:

+ `, + }); + + let area = 5 * 2 + 1 + (8 * 5) / 2; + let perimeter = 5 + 2 * Math.sqrt(2) + Math.sqrt(25 + 64) + 10; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/area"].stateValues.value).eq(area); + expect(stateVariables["/perimeter"].stateValues.value).eq(perimeter); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: { 1: [-8, -4] }, + }, + event: null, + }); + await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: { 2: [-8, 2] }, + }, + event: null, + }); + + area = 2 * 8 + (4 * 8) / 2 - (5 * 8) / 2; + perimeter = 13 + 6 + Math.sqrt(16 + 64) + 10 + Math.sqrt(25 + 64); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/area"].stateValues.value).eq(area); + expect(stateVariables["/perimeter"].stateValues.value).eq(perimeter); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: { 3: [8, 2] }, + }, + event: null, + }); + + area = 0; + perimeter = 16 + 6 + Math.sqrt(16 + 64) + 10 + Math.sqrt(64 + 64); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/area"].stateValues.value).eq(area); + expect(stateVariables["/perimeter"].stateValues.value).eq(perimeter); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/p", + args: { + pointCoords: { 0: [0, 2] }, + }, + event: null, + }); + + area = (8 * 8) / 2 - (8 * 6) / 2; + perimeter = 16 + 6 + Math.sqrt(36 + 64) + 8 + Math.sqrt(64 + 64); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/area"].stateValues.value).eq(area); + expect(stateVariables["/perimeter"].stateValues.value).eq(perimeter); + }); + + it("Rigid polygon", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + let centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees counterclockwise around centroid + // (shrinking by 1/2, but that will be ignored) + let requested_vertex_1 = [ + -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + -(v[1] - centroid[1]) + centroid[0], + v[0] - centroid[0] + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to the right choosminimum moved"); + let moveX = 3; + let moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex, gettirotation"); + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 180 degrees around centroid + // (doubling length, but that will be ignored) + let requested_vertex_2 = [ + -2 * (vertices[2][0] - centroid[0]) + centroid[0], + -2 * (vertices[2][1] - centroid[1]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + -(v[0] - centroid[0]) + centroid[0], + -(v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving single copied vertex gets rotation + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees clockwise around centroid + // (shrinking by 1/4, but that will be ignored) + let requested_vertex_3 = [ + 0.25 * (vertices[3][1] - centroid[1]) + centroid[0], + -0.25 * (vertices[3][0] - centroid[0]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + v[1] - centroid[1] + centroid[0], + -(v[0] - centroid[0]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Preserve similarity", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex rotates and dilates + let centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees counterclockwise around centroid + // and shrinking by 1/2 + let requested_vertex_1 = [ + -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + -0.5 * (v[1] - centroid[1]) + centroid[0], + 0.5 * (v[0] - centroid[0]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to the right choosminimum moved"); + let moveX = 3; + let moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex, getting rotation and dilation + + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 180 degrees around centroid + // and doubling length + let requested_vertex_2 = [ + -2 * (vertices[2][0] - centroid[0]) + centroid[0], + -2 * (vertices[2][1] - centroid[1]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + -2 * (v[0] - centroid[0]) + centroid[0], + -2 * (v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving single copied vertex gets rotation adilation"); + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees clockwise around centroid + // and shrinking by 1/4 + let requested_vertex_3 = [ + 0.25 * (vertices[3][1] - centroid[1]) + centroid[0], + -0.25 * (vertices[3][0] - centroid[0]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + 0.25 * (v[1] - centroid[1]) + centroid[0], + -0.25 * (v[0] - centroid[0]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Preserve similarity and don't allow dilation equals rigid", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex rotates + let centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees counterclockwise around centroid + // (shrinking by 1/2, but that will be ignored) + let requested_vertex_1 = [ + -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + -(v[1] - centroid[1]) + centroid[0], + v[0] - centroid[0] + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to the right choosminimum moved"); + let moveX = 3; + let moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Rigid supersedes setting preserveSimilarity to false or allowDilation to true", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex rotates + let centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees counterclockwise around centroid + // (shrinking by 1/2, but that will be ignored) + let requested_vertex_1 = [ + -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + -(v[1] - centroid[1]) + centroid[0], + v[0] - centroid[0] + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to the right choosminimum moved"); + let moveX = 3; + let moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Don't allow rotation", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex only dilates + let centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // shrink to half size by moving vertex so projects to half + // on the segment from centroid to original vertex + let midpoint = [ + (centroid[0] + vertices[1][0]) / 2, + (centroid[1] + vertices[1][1]) / 2, + ]; + let vector_to_v1 = [ + vertices[1][0] - centroid[0], + vertices[1][1] - centroid[1], + ]; + let rotate_vector = [-3 * vector_to_v1[1], 3 * vector_to_v1[0]]; + + let requested_vertex_1 = [ + midpoint[0] + rotate_vector[0], + midpoint[1] + rotate_vector[1], + ]; + vertices = vertices.map((v) => [ + 0.5 * (v[0] - centroid[0]) + centroid[0], + 0.5 * (v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to the right choosminimum moved"); + let moveX = 3; + let moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex, attempting to rotation 90 degrees shrinks to minimum + + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // attempt to rotate by 90 degrees around centroid + let requested_vertex_2 = [ + 2 * (vertices[2][1] - centroid[1]) + centroid[0], + -2 * (vertices[2][0] - centroid[0]) + centroid[1], + ]; + + // distance from vertex 2 and centroid becomes minShrink = 0.1 + let shrink_factor = + 0.1 / + Math.sqrt( + (vertices[2][1] - centroid[1]) ** 2 + + (vertices[2][0] - centroid[0]) ** 2, + ); + + vertices = vertices.map((v) => [ + shrink_factor * (v[0] - centroid[0]) + centroid[0], + shrink_factor * (v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving single copied vertex to dilate + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // Make 10 times larger by moving vertex so projects to 10 times the length on + // on the segment from centroid to original vertex + let extended_point = [ + 10 * vertices[3][0] - 9 * centroid[0], + 10 * vertices[3][1] - 9 * centroid[1], + ]; + let vector_to_v3 = [ + vertices[3][0] - centroid[0], + vertices[3][1] - centroid[1], + ]; + rotate_vector = [0.5 * vector_to_v3[1], -0.5 * vector_to_v3[0]]; + + let requested_vertex_3 = [ + extended_point[0] + rotate_vector[0], + extended_point[1] + rotate_vector[1], + ]; + vertices = vertices.map((v) => [ + 10 * (v[0] - centroid[0]) + centroid[0], + 10 * (v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Don't allow rotation, large minShrink", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex only dilates + let centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // shrink to half size by moving vertex so projects to half + // on the segment from centroid to original vertex + let midpoint = [ + (centroid[0] + vertices[1][0]) / 2, + (centroid[1] + vertices[1][1]) / 2, + ]; + let vector_to_v1 = [ + vertices[1][0] - centroid[0], + vertices[1][1] - centroid[1], + ]; + let rotate_vector = [-3 * vector_to_v1[1], 3 * vector_to_v1[0]]; + + let requested_vertex_1 = [ + midpoint[0] + rotate_vector[0], + midpoint[1] + rotate_vector[1], + ]; + vertices = vertices.map((v) => [ + 0.5 * (v[0] - centroid[0]) + centroid[0], + 0.5 * (v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to the right chooses minimum moved + let moveX = 3; + let moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex, attempting to rotation 90 degrees shrinks to minimum + + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // attempt to rotate by 90 degrees around centroid + let requested_vertex_2 = [ + 2 * (vertices[2][1] - centroid[1]) + centroid[0], + -2 * (vertices[2][0] - centroid[0]) + centroid[1], + ]; + + // distance from vertex 2 and centroid becomes minShrink = 0.1 + let shrink_factor = + 2 / + Math.sqrt( + (vertices[2][1] - centroid[1]) ** 2 + + (vertices[2][0] - centroid[0]) ** 2, + ); + + vertices = vertices.map((v) => [ + shrink_factor * (v[0] - centroid[0]) + centroid[0], + shrink_factor * (v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving single copied vertex to dilate + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // Make 10 times larger by moving vertex so projects to 10 times the length on + // on the segment from centroid to original vertex + let extended_point = [ + 10 * vertices[3][0] - 9 * centroid[0], + 10 * vertices[3][1] - 9 * centroid[1], + ]; + let vector_to_v3 = [ + vertices[3][0] - centroid[0], + vertices[3][1] - centroid[1], + ]; + rotate_vector = [0.5 * vector_to_v3[1], -0.5 * vector_to_v3[0]]; + + let requested_vertex_3 = [ + extended_point[0] + rotate_vector[0], + extended_point[1] + rotate_vector[1], + ]; + vertices = vertices.map((v) => [ + 10 * (v[0] - centroid[0]) + centroid[0], + 10 * (v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Don't allow translation", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex rotates and dilates + let centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees counterclockwise around centroid + // and shrinking by 1/2 + let requested_vertex_1 = [ + -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + -0.5 * (v[1] - centroid[1]) + centroid[0], + 0.5 * (v[0] - centroid[0]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up does not move + let moveX = 3; + let moveY = 2; + + // this translation will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + requested_vertices.push([ + vertices[i][0] + moveX, + vertices[i][1] + moveY, + ]); + } + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex, getting rotation and dilation + + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 180 degrees around centroid + // and doubling length + let requested_vertex_2 = [ + -2 * (vertices[2][0] - centroid[0]) + centroid[0], + -2 * (vertices[2][1] - centroid[1]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + -2 * (v[0] - centroid[0]) + centroid[0], + -2 * (v[1] - centroid[1]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving single copied vertex gets rotation adilation"); + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees clockwise around centroid + // and shrinking by 1/4 + let requested_vertex_3 = [ + 0.25 * (vertices[3][1] - centroid[1]) + centroid[0], + -0.25 * (vertices[3][0] - centroid[0]) + centroid[1], + ]; + vertices = vertices.map((v) => [ + 0.25 * (v[1] - centroid[1]) + centroid[0], + -0.25 * (v[0] - centroid[0]) + centroid[1], + ]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Only translation", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex translates + let moveX = -1; + let moveY = -3; + let requested_vertex_1 = [ + vertices[1][0] + moveX, + vertices[1][1] + moveY, + ]; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to right + moveX = 3; + moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex, getting translation + moveX = -8; + moveY = 4; + let requested_vertex_2 = [ + vertices[2][0] + moveX, + vertices[2][1] + moveY, + ]; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving single copied vertex gets translation + moveX = 2; + moveY = -5; + let requested_vertex_3 = [ + vertices[3][0] + moveX, + vertices[3][1] + moveY, + ]; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Don't allow any transformations", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex doesn't move + let centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees counterclockwise around centroid + // and shrinking by 1/2 + // but no effect + let requested_vertex_1 = [ + -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + ]; + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 1: requested_vertex_1 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up does not move + let moveX = 3; + let moveY = 2; + + // this translation will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + requested_vertices.push([ + vertices[i][0] + moveX, + vertices[i][1] + moveY, + ]); + } + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex doesn't move + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 180 degrees around centroid + // and doubling length + // but no effect + let requested_vertex_2 = [ + -2 * (vertices[2][0] - centroid[0]) + centroid[0], + -2 * (vertices[2][1] - centroid[1]) + centroid[1], + ]; + + await await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving single copied vertex doesn't move + centroid = vertices.reduce( + (a, c) => [a[0] + c[0], a[1] + c[1]], + [0, 0], + ); + centroid[0] /= 4; + centroid[1] /= 4; + + // rotate by 90 degrees clockwise around centroid + // and shrinking by 1/4 + // but no effect + let requested_vertex_3 = [ + 0.25 * (vertices[3][1] - centroid[1]) + centroid[0], + -0.25 * (vertices[3][0] - centroid[0]) + centroid[1], + ]; + + await await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Rotate around vertex", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex rotates and dilates + let rotationPoint = vertices[1]; + + // rotate by 90 degrees counterclockwise around rotationPoint + // and shrinking by 1/2 + let requested_vertex_0 = [ + -0.5 * (vertices[0][1] - rotationPoint[1]) + rotationPoint[0], + 0.5 * (vertices[0][0] - rotationPoint[0]) + rotationPoint[1], + ]; + vertices = vertices.map((v) => [ + -0.5 * (v[1] - rotationPoint[1]) + rotationPoint[0], + 0.5 * (v[0] - rotationPoint[0]) + rotationPoint[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 0: requested_vertex_0 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to the right chooses minimum moved + let moveX = 3; + let moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex, getting rotation and dilation + + rotationPoint = vertices[1]; + + // rotate by 180 degrees around rotationPoint + // and doubling length + let requested_vertex_2 = [ + -2 * (vertices[2][0] - rotationPoint[0]) + rotationPoint[0], + -2 * (vertices[2][1] - rotationPoint[1]) + rotationPoint[1], + ]; + vertices = vertices.map((v) => [ + -2 * (v[0] - rotationPoint[0]) + rotationPoint[0], + -2 * (v[1] - rotationPoint[1]) + rotationPoint[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving single copied vertex gets rotation and dilation + rotationPoint = vertices[1]; + + // rotate by 90 degrees clockwise around rotationPoint + // and shrinking by 1/4 + let requested_vertex_3 = [ + 0.25 * (vertices[3][1] - rotationPoint[1]) + rotationPoint[0], + -0.25 * (vertices[3][0] - rotationPoint[0]) + rotationPoint[1], + ]; + vertices = vertices.map((v) => [ + 0.25 * (v[1] - rotationPoint[1]) + rotationPoint[0], + -0.25 * (v[0] - rotationPoint[0]) + rotationPoint[1], + ]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); + + it("Rotate around exterior point", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,7) + (-4,-1) + (8,2) + (-3,4) + (-1,3) + + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 7], + [-4, -1], + [8, 2], + [-3, 4], + ]; + + await testPolygonCopiedTwice({ vertices, core }); + + // move individual vertex rotates and dilates + let rotationPoint = [-1, 3]; + + // rotate by 90 degrees counterclockwise around rotationPoint + // and shrinking by 1/2 + let requested_vertex_0 = [ + -0.5 * (vertices[0][1] - rotationPoint[1]) + rotationPoint[0], + 0.5 * (vertices[0][0] - rotationPoint[0]) + rotationPoint[1], + ]; + vertices = vertices.map((v) => [ + -0.5 * (v[1] - rotationPoint[1]) + rotationPoint[0], + 0.5 * (v[0] - rotationPoint[0]) + rotationPoint[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g1/pg", + args: { + pointCoords: { 0: requested_vertex_0 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move copied polygon up and to the right chooses minimum moved + let moveX = 3; + let moveY = 2; + + // add extra movement to requested vertices, which will be ignored + let requested_vertices: number[][] = []; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + requested_vertices.push([ + vertices[i][0] + i, + vertices[i][1] + 2 * i, + ]); + } + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g2/pg", + args: { + pointCoords: requested_vertices, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // move double copied individual vertex, getting rotation and dilation + + rotationPoint = [-1, 3]; + + // rotate by 180 degrees around rotationPoint + // and doubling length + let requested_vertex_2 = [ + -2 * (vertices[2][0] - rotationPoint[0]) + rotationPoint[0], + -2 * (vertices[2][1] - rotationPoint[1]) + rotationPoint[1], + ]; + vertices = vertices.map((v) => [ + -2 * (v[0] - rotationPoint[0]) + rotationPoint[0], + -2 * (v[1] - rotationPoint[1]) + rotationPoint[1], + ]); + + await core.requestAction({ + actionName: "movePolygon", + componentName: "/g3/pg", + args: { + pointCoords: { 2: requested_vertex_2 }, + }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // change rotation point, then moving single copied vertex gets rotation and dilation + + await await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/rotationPoint", + args: { x: 6, y: -2 }, + event: null, + }); + + rotationPoint = [6, -2]; + + // rotate by 90 degrees clockwise around rotationPoint + // and shrinking by 1/4 + let requested_vertex_3 = [ + 0.25 * (vertices[3][1] - rotationPoint[1]) + rotationPoint[0], + -0.25 * (vertices[3][0] - rotationPoint[0]) + rotationPoint[1], + ]; + vertices = vertices.map((v) => [ + 0.25 * (v[1] - rotationPoint[1]) + rotationPoint[0], + -0.25 * (v[0] - rotationPoint[0]) + rotationPoint[1], + ]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/v4", + args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + + // moving defining vertex deforms polygon + vertices[0] = [4, 6]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/_point1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + + await testPolygonCopiedTwice({ vertices, core }); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/polyline.test.ts b/packages/doenetml-worker/src/test/tagSpecific/polyline.test.ts new file mode 100644 index 000000000..f027389f9 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/polyline.test.ts @@ -0,0 +1,4588 @@ +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); + +async function testPolylineCopiedTwice({ + core, + vertices, + polylineName = "/pg", + graph1Name = "/g1", + graph2Name = "/g2", + graph3Name = "/g3", +}: { + core: any; + vertices: (number | string)[][]; + polylineName?: string; + graph1Name?: string; + graph2Name?: string; + graph3Name?: string; +}) { + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables[graph1Name + polylineName].stateValues.numVertices, + ).eqls(vertices.length); + expect( + stateVariables[graph2Name + polylineName].stateValues.numVertices, + ).eqls(vertices.length); + expect( + stateVariables[graph3Name + polylineName].stateValues.numVertices, + ).eqls(vertices.length); + + for (let i in vertices) { + if ( + typeof vertices[i][0] === "number" && + Number.isFinite(vertices[i][0]) + ) { + expect( + me + .fromAst( + stateVariables[graph1Name + polylineName].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + expect( + me + .fromAst( + stateVariables[graph2Name + polylineName].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + expect( + me + .fromAst( + stateVariables[graph3Name + polylineName].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + } else { + expect( + stateVariables[graph1Name + polylineName].stateValues.vertices[ + i + ][0].tree, + ).eq(vertices[i][0]); + expect( + stateVariables[graph2Name + polylineName].stateValues.vertices[ + i + ][0].tree, + ).eq(vertices[i][0]); + expect( + stateVariables[graph3Name + polylineName].stateValues.vertices[ + i + ][0].tree, + ).eq(vertices[i][0]); + } + if ( + typeof vertices[i][1] === "number" && + Number.isFinite(vertices[i][1]) + ) { + expect( + me + .fromAst( + stateVariables[graph1Name + polylineName].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + expect( + me + .fromAst( + stateVariables[graph2Name + polylineName].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + expect( + me + .fromAst( + stateVariables[graph3Name + polylineName].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + } else { + expect( + stateVariables[graph1Name + polylineName].stateValues.vertices[ + i + ][1].tree, + ).eq(vertices[i][1]); + expect( + stateVariables[graph2Name + polylineName].stateValues.vertices[ + i + ][1].tree, + ).eq(vertices[i][1]); + expect( + stateVariables[graph3Name + polylineName].stateValues.vertices[ + i + ][1].tree, + ).eq(vertices[i][1]); + } + } +} + +describe("Polyline tag tests", async () => { + it("Polyline vertices and copied points", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,5) + (-4,-1) + (5,2) + (-3,4) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 5], + [-4, -1], + [5, 2], + [-3, 4], + ]; + + await testPolylineCopiedTwice({ core, vertices }); + + // move individual vertex + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move copied polyline up and to the right + let moveX = 3; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move double copied individual vertex + vertices[2] = [-9, -8]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g3/pg", + args: { + pointCoords: { 2: vertices[2] }, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + }); + + it("Polyline macro in vertices", async () => { + let core = await createTestCore({ + doenetML: ` + -1 + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 5], + [-4, -1], + [5, 2], + [-3, 4], + ]; + + await testPolylineCopiedTwice({ core, vertices }); + + // move individual vertex + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move copied polyline up and to the right + let moveX = 3; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move double copied individual vertex + vertices[2] = [-9, -8]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g3/pg", + args: { + pointCoords: { 2: vertices[2] }, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + }); + + it("dynamic polyline with vertices from copied map, initially zero, copied", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices: number[][] = []; + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "1", + componentName: "/length", + core, + }); + vertices[0] = [0, 5 * Math.sin(0)]; + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "2", + componentName: "/length", + core, + }); + vertices[1] = [1, 5 * Math.sin(1)]; + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "3", + componentName: "/length", + core, + }); + vertices[2] = [2, 5 * Math.sin(2)]; + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "2", + componentName: "/length", + core, + }); + vertices.splice(2, 1); + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "0", + componentName: "/length", + core, + }); + vertices = []; + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "5", + componentName: "/length", + core, + }); + for (let i = 0; i < 5; i++) { + vertices.push([i, 5 * Math.sin(i)]); + } + await testPolylineCopiedTwice({ core, vertices }); + + // start over and begin with big increment + core = await createTestCore({ + doenetML: ` + + + + + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + vertices = []; + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "10", + componentName: "/length", + core, + }); + for (let i = 0; i < 10; i++) { + vertices.push([i, 5 * Math.sin(i)]); + } + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "1", + componentName: "/length", + core, + }); + vertices = [[0, 5 * Math.sin(0)]]; + await testPolylineCopiedTwice({ core, vertices }); + }); + + it("polyline with initially undefined point", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [1, 2], + [-1, 5], + ["\uff3f", 7], + [3, -5], + [-4, -3], + ]; + await testPolylineCopiedTwice({ core, vertices }); + + await updateMathInputValue({ + latex: "-2", + componentName: "/mi", + core, + }); + + vertices[2][0] = -2; + await testPolylineCopiedTwice({ core, vertices }); + }); + + it(`can't move polyline based on map`, async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices: number[][] = []; + for (let i = -5; i <= 5; i++) { + vertices.push([i, 5 * Math.sin(i)]); + } + await testPolylineCopiedTwice({ core, vertices }); + + // can't move points + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/mp1", + args: { x: 9, y: -8 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/mp9", + args: { x: -8, y: 4 }, + event: null, + }); + + // can't move polyline1 + let moveX = 3; + let moveY = 2; + + let vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // can't move polyline2 + moveX = -5; + moveY = 6; + + vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // can't move polyline3 + moveX = 7; + moveY = -4; + + vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g3/pg", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + }); + + it(`create moveable polyline based on map`, async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices: number[][] = []; + for (let i = -5; i <= 5; i++) { + vertices.push([i, 5 * Math.sin(i)]); + } + await testPolylineCopiedTwice({ core, vertices }); + + // can move points + + vertices[0] = [9, -8]; + vertices[8] = [-8, 4]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/mp1", + args: { x: vertices[0][0], y: vertices[0][1] }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/g1/mp9", + args: { x: vertices[8][0], y: vertices[8][1] }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // can move polyline1 + let moveX = 3; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // can move polyline2 + moveX = -5; + moveY = 6; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + moveX = 7; + moveY = -4; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + }); + + it("copy vertices of polyline", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $pl.vertex1{assignNames="v1"} + $pl.vertex2{assignNames="v2"} + $pl.vertex3{assignNames="v3"} + $pl.vertex4{assignNames="v4"} + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let ps = [ + [-3, -1], + [1, 2], + [3, 4], + [6, -2], + ]; + + for (let i = 0; i < 4; i++) { + expect(stateVariables[`/v${i + 1}`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + } + + // move individually copied vertices + ps = [ + [-5, 3], + [-2, 7], + [0, -8], + [9, -6], + ]; + + for (let i = 0; i < 4; i++) { + await core.requestAction({ + actionName: "movePoint", + componentName: `/v${i + 1}`, + args: { x: ps[i][0], y: ps[i][1] }, + event: null, + }); + } + + stateVariables = await returnAllStateVariables(core); + for (let i = 0; i < 4; i++) { + expect(stateVariables[`/v${i + 1}`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + } + + // move array-copied vertices + ps = [ + [-7, -1], + [-3, 5], + [2, 4], + [6, 0], + ]; + + for (let i = 0; i < 4; i++) { + await core.requestAction({ + actionName: "movePoint", + componentName: `/v${i + 1}a`, + args: { x: ps[i][0], y: ps[i][1] }, + event: null, + }); + } + + stateVariables = await returnAllStateVariables(core); + for (let i = 0; i < 4; i++) { + expect(stateVariables[`/v${i + 1}`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0].tree).eq( + ps[i][0], + ); + expect(stateVariables[`/v${i + 1}`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1].tree).eq( + ps[i][1], + ); + } + }); + + it("new polyline from copied vertices of polyline", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + $g2{name="g3"} + `, + }); + + let vertices = [ + [-9, 6], + [-3, 7], + [4, 0], + [8, 5], + ]; + + await testPolylineCopiedTwice({ core, vertices }); + + // move first polyline up and to the right + let moveX = 4; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move copied polyline up and to the left + moveX = -7; + moveY = 3; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move double copied polyline down and to the left + moveX = -1; + moveY = -4; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] += moveX; + vertices[i][1] += moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g3/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + }); + + it("new polyline as translated version of polyline", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + $_polyline1.vertices{name="vs"} + + + + + $_polyline2.vertices{assignNames="p1 p2 p3 p4"} + + `, + }); + + async function testPolylines({ vertices, transX, transY }) { + let vertices2 = vertices.map((v) => [v[0] + transX, v[1] + transY]); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_polyline1"].stateValues.numVertices).eqls( + vertices.length, + ); + expect(stateVariables["/_polyline2"].stateValues.numVertices).eqls( + vertices.length, + ); + + for (let i in vertices) { + if (Number.isFinite(vertices[i][0])) { + expect( + me + .fromAst( + stateVariables["/_polyline1"].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + expect( + me + .fromAst( + stateVariables["/_polyline2"].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices2[i][0], 1e-12); + } else { + expect( + stateVariables["/_polyline1"].stateValues.vertices[i][0] + .tree, + ).eq(vertices[i][0]); + expect( + stateVariables["/_polyline2"].stateValues.vertices[i][0] + .tree, + ).eq(vertices2[i][0]); + } + if (Number.isFinite(vertices[i][1])) { + expect( + me + .fromAst( + stateVariables["/_polyline1"].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + expect( + me + .fromAst( + stateVariables["/_polyline2"].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices2[i][1], 1e-12); + } else { + expect( + stateVariables["/_polyline1"].stateValues.vertices[i][1] + .tree, + ).eq(vertices[i][1]); + expect( + stateVariables["/_polyline2"].stateValues.vertices[i][1] + .tree, + ).eq(vertices2[i][1]); + } + } + } + + let vertices = [ + [0, 0], + [3, -4], + [1, -6], + [-5, -6], + ]; + let transX = 5; + let transY = 7; + + await testPolylines({ vertices, transX, transY }); + + // move points on first polyline + vertices = [ + [1, -1], + [-3, 2], + [-1, 7], + [6, 3], + ]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylines({ vertices, transX, transY }); + + // move points on second polyline + let vertices2 = [ + [-3, 4], + [1, 0], + [9, 6], + [2, -1], + ]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline2", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + vertices = vertices2.map((v) => [v[0] - transX, v[1] - transY]); + + await testPolylines({ vertices, transX, transY }); + + // change translation + await updateMathInputValue({ + latex: "2", + componentName: "/transx", + core, + }); + await updateMathInputValue({ + latex: "10", + componentName: "/transy", + core, + }); + + transX = 2; + transY = 10; + + await testPolylines({ vertices, transX, transY }); + }); + + it("open parallelogram based on three points", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + let D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move first vertex + A = [-4, -1]; + D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/parallelogram", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + B = [8, 9]; + D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/parallelogram", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move third vertex + C = [-3, 7]; + D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/parallelogram", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move fourth vertex + D = [7, 0]; + B = [A[0] + C[0] - D[0], A[1] + C[1] - D[1]]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/parallelogram", + args: { + pointCoords: { 3: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/parallelogram"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/parallelogram"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/parallelogram"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/parallelogram"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + }); + + it("new polyline from copied vertices, some flipped", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + `, + }); + + async function testPolylines({ vertices }) { + let vertices2 = [...vertices]; + vertices2[1] = [vertices2[1][1], vertices2[1][0]]; + vertices2[3] = [vertices2[3][1], vertices2[3][0]]; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_polyline1"].stateValues.numVertices).eqls( + vertices.length, + ); + expect(stateVariables["/_polyline2"].stateValues.numVertices).eqls( + vertices.length, + ); + + for (let i in vertices) { + if (Number.isFinite(vertices[i][0])) { + expect( + me + .fromAst( + stateVariables["/_polyline1"].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][0], 1e-12); + expect( + me + .fromAst( + stateVariables["/_polyline2"].stateValues + .vertices[i][0], + ) + .evaluate_to_constant(), + ).closeTo(vertices2[i][0], 1e-12); + } else { + expect( + stateVariables["/_polyline1"].stateValues.vertices[i][0] + .tree, + ).eq(vertices[i][0]); + expect( + stateVariables["/_polyline2"].stateValues.vertices[i][0] + .tree, + ).eq(vertices2[i][0]); + } + if (Number.isFinite(vertices[i][1])) { + expect( + me + .fromAst( + stateVariables["/_polyline1"].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices[i][1], 1e-12); + expect( + me + .fromAst( + stateVariables["/_polyline2"].stateValues + .vertices[i][1], + ) + .evaluate_to_constant(), + ).closeTo(vertices2[i][1], 1e-12); + } else { + expect( + stateVariables["/_polyline1"].stateValues.vertices[i][1] + .tree, + ).eq(vertices[i][1]); + expect( + stateVariables["/_polyline2"].stateValues.vertices[i][1] + .tree, + ).eq(vertices2[i][1]); + } + } + } + + let vertices = [ + [-9, 6], + [-3, 7], + [4, 0], + [8, 5], + ]; + + await testPolylines({ vertices }); + + // move first polyline vertices + vertices = [ + [7, 2], + [1, -3], + [2, 9], + [-4, -3], + ]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylines({ vertices }); + + // move second polyline vertices + let vertices2 = [ + [-1, 9], + [5, 7], + [-8, 1], + [-7, 6], + ]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline2", + args: { + pointCoords: vertices2, + }, + event: null, + }); + + vertices = [...vertices2]; + vertices[1] = [vertices[1][1], vertices[1][0]]; + vertices[3] = [vertices[3][1], vertices[3][0]]; + + await testPolylines({ vertices }); + }); + + it("four vertex polyline based on three points", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + let D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move first vertex + A = [-4, -1]; + D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move second vertex + B = [8, 9]; + D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move third vertex + C = [-3, 7]; + D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + + // move fourth vertex + D = [7, 0]; + A = [C[0] + B[0] - D[0], C[1] + B[1] - D[1]]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 3: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(D); + }); + + it("fourth vertex depends on internal copy of first vertex", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_polyline1"].stateValues.numVertices).eq(4); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move first vertex + A = [-4, -1]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move fourth vertex + A = [7, 0]; + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 3: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + }); + + it("first vertex depends on internal copy of fourth vertex", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_polyline1"].stateValues.numVertices).eq(4); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move first vertex + A = [-4, -1]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + + // move fourth vertex + A = [7, 0]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 3: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + }); + + it("first vertex depends fourth, formula for fifth", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + + $_polyline1.vertices{assignNames="p1 p2 p3 p4 p5"} + + `, + }); + + let A = [1, 2]; + let B = [3, 4]; + let C = [-5, 6]; + let D = [A[0] + 1, 2]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move first vertex + A = [-4, -1]; + D[0] = A[0] + 1; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move fourth vertex + A = [7, 0]; + D[0] = A[0] + 1; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 3: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + + // move fifth vertex + D = [-5, 9]; + A[0] = D[0] - 1; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 4: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/_polyline1"].stateValues.vertices[0].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[1].map( + (x) => x.tree, + ), + ).eqls(B); + expect( + stateVariables["/_polyline1"].stateValues.vertices[2].map( + (x) => x.tree, + ), + ).eqls(C); + expect( + stateVariables["/_polyline1"].stateValues.vertices[3].map( + (x) => x.tree, + ), + ).eqls(A); + expect( + stateVariables["/_polyline1"].stateValues.vertices[4].map( + (x) => x.tree, + ), + ).eqls(D); + }); + + it("first, fourth, seventh vertex depends on fourth, seventh, tenth", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let A = [-5, -1]; + let B = [1, 2]; + let C = [3, 4]; + let D = [5, 7]; + let E = [-5, 7]; + let F = [3, 1]; + let G = [5, 0]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move first vertex + A = [-4, -9]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 0: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move fourth vertex + A = [7, 0]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 3: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move fifth vertex + D = [-9, 1]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 4: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move sixth vertex + E = [-3, 6]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 5: E }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move seventh vertex + A = [2, -4]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 6: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move eighth vertex + F = [6, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 7: F }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move ninth vertex + G = [1, -8]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 8: G }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move tenth vertex + A = [-6, 10]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 9: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + }); + + it("first, fourth, seventh vertex depends on shifted fourth, seventh, tenth", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + + $P.vertices{assignNames="p1 p2 p3 p4 p5 p6 p7 p8 p9 p10"} + + `, + }); + + let A = [-5, -1]; + let B = [1, 2]; + let C = [3, 4]; + let D = [5, 7]; + let E = [-5, 7]; + let F = [3, 1]; + let G = [5, 0]; + let A1 = [A[0] + 1, A[1] + 1]; + let A2 = [A[0] + 2, A[1] + 2]; + let A3 = [A[0] + 3, A[1] + 3]; + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move first vertex + A = [-4, -9]; + A1 = [A[0] + 1, A[1] + 1]; + A2 = [A[0] + 2, A[1] + 2]; + A3 = [A[0] + 3, A[1] + 3]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 0: A3 }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move second vertex + B = [8, 9]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 1: B }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move third vertex + C = [-3, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 2: C }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move fourth vertex + A = [7, 0]; + A1 = [A[0] + 1, A[1] + 1]; + A2 = [A[0] + 2, A[1] + 2]; + A3 = [A[0] + 3, A[1] + 3]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 3: A2 }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move fifth vertex + D = [-9, 1]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 4: D }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move sixth vertex + E = [-3, 6]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 5: E }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move seventh vertex + A = [2, -4]; + A1 = [A[0] + 1, A[1] + 1]; + A2 = [A[0] + 2, A[1] + 2]; + A3 = [A[0] + 3, A[1] + 3]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 6: A1 }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move eighth vertex + F = [6, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 7: F }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move ninth vertex + G = [1, -8]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 8: G }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + + // move tenth vertex + A = [-6, 7]; + A1 = [A[0] + 1, A[1] + 1]; + A2 = [A[0] + 2, A[1] + 2]; + A3 = [A[0] + 3, A[1] + 3]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/P", + args: { + pointCoords: { 9: A }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/P"].stateValues.vertices[0].map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/P"].stateValues.vertices[1].map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/P"].stateValues.vertices[2].map((x) => x.tree), + ).eqls(C); + expect( + stateVariables["/P"].stateValues.vertices[3].map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/P"].stateValues.vertices[4].map((x) => x.tree), + ).eqls(D); + expect( + stateVariables["/P"].stateValues.vertices[5].map((x) => x.tree), + ).eqls(E); + expect( + stateVariables["/P"].stateValues.vertices[6].map((x) => x.tree), + ).eqls(A1); + expect( + stateVariables["/P"].stateValues.vertices[7].map((x) => x.tree), + ).eqls(F); + expect( + stateVariables["/P"].stateValues.vertices[8].map((x) => x.tree), + ).eqls(G); + expect( + stateVariables["/P"].stateValues.vertices[9].map((x) => x.tree), + ).eqls(A); + }); + + it("attract to polyline", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $_polyline1 + + + + `, + }); + + let x1 = 3, + x2 = -4, + x3 = 5; + let y1 = 5, + y2 = -1, + y3 = 2; + + // point originally not attracted + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_point1"].stateValues.coords.tree).eqls([ + "vector", + 7, + 8, + ]); + + // move point near segment 1 + let x = 1; + let mseg1 = (y2 - y1) / (x2 - x1); + let y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + let px = stateVariables["/_point1"].stateValues.xs[0].tree; + let py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move point near segment 2 + x = 3; + let mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.4; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + + // move point near segment between first and last vertices + x = 4; + let mseg3 = (y1 - y3) / (x1 - x3); + y = mseg3 * (x - x3) + y3 + 0.2; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + // move point just past first vertex + x = x1 + 0.2; + y = y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x1, 1e-6); + expect(py).closeTo(y1, 1e-6); + + // point not attracted along extension of first segment + x = 4; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + x = -5; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + // move point just past second vertex + x = x2 - 0.2; + y = y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // point not attracted along extension of second segment + x = 6; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + x = -5; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x, 1e-6); + expect(py).closeTo(y, 1e-6); + + // move polyline so point attracts to first segment + let moveX = -3; + let moveY = -2; + + x1 += moveX; + x2 += moveX; + x3 += moveX; + y1 += moveY; + y2 += moveY; + y3 += moveY; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: [ + [x1, y1], + [x2, y2], + [x3, y3], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg1 = (y2 - y1) / (x2 - x1); + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move second vertex so point attracts to second segment + moveX = -1; + moveY = 1; + + x2 += moveX; + y2 += moveY; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 1: [x2, y2] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg2 = (y2 - y3) / (x2 - x3); + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + }); + + it("constrain to polyline", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $_polyline1 + + + + `, + }); + + let x1 = 3, + x2 = -4, + x3 = 5; + let y1 = 5, + y2 = -1, + y3 = 2; + + // point originally constrained + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_point1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + + // move point near segment 1 + let x = 1; + let mseg1 = (y2 - y1) / (x2 - x1); + let y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + let px = stateVariables["/_point1"].stateValues.xs[0].tree; + let py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move point near segment 2 + x = 3; + let mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.4; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + + // move point near segment between first and last vertices + + x = 4; + let mseg3 = (y1 - y3) / (x1 - x3); + y = mseg3 * (x - x3) + y3 + 0.2; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + mseg1 = (y2 - y1) / (x2 - x1); + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move point just past first vertex + + x = x1 + 0.2; + y = y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x1, 1e-6); + expect(py).closeTo(y1, 1e-6); + + //point along extension of first segment constrained to endpoint + + x = 4; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x1, 1e-6); + expect(py).closeTo(y1, 1e-6); + x = -5; + mseg1 = (y2 - y1) / (x2 - x1); + y = mseg1 * (x - x1) + y1 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // move point just past second vertex + + x = x2 - 0.2; + y = y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + //point along extension of second segment constrained to endpoint + + x = 6; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 + 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x3, 1e-6); + expect(py).closeTo(y3, 1e-6); + + x = -5; + mseg2 = (y2 - y3) / (x2 - x3); + y = mseg2 * (x - x2) + y2 - 0.3; + + await core.requestAction({ + actionName: "movePoint", + componentName: `/_point1`, + args: { x, y }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + expect(px).closeTo(x2, 1e-6); + expect(py).closeTo(y2, 1e-6); + + // move polyline so point constrained to first segment + + let moveX = -3; + let moveY = -5; + + x1 += moveX; + x2 += moveX; + x3 += moveX; + y1 += moveY; + y2 += moveY; + y3 += moveY; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: [ + [x1, y1], + [x2, y2], + [x3, y3], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg1 = (y2 - y1) / (x2 - x1); + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move second vertex so point constrained to second segment + + moveX = -1; + moveY = 8; + + x2 += moveX; + y2 += moveY; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/_polyline1", + args: { + pointCoords: { 1: [x2, y2] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + px = stateVariables["/_point1"].stateValues.xs[0].tree; + py = stateVariables["/_point1"].stateValues.xs[1].tree; + + mseg2 = (y2 - y3) / (x2 - x3); + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + }); + + it("constrain to polyline, different scales from graph", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $p + + + + `, + }); + + let x1 = -50, + x2 = -40, + x3 = 70, + x4 = 10; + let y1 = -0.02, + y2 = 0.07, + y3 = 0.06, + y4 = -0.01; + + // point originally on segment 3 + + let stateVariables = await returnAllStateVariables(core); + + let mseg3 = (y4 - y3) / (x4 - x3); + + let px = stateVariables["/A"].stateValues.xs[0].tree; + let py = stateVariables["/A"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); + + // move point near segment 1 + + let mseg1 = (y2 - y1) / (x2 - x1); + + await core.requestAction({ + actionName: "movePoint", + componentName: `/A`, + args: { x: -20, y: 0.02 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/A"].stateValues.xs[0].tree; + py = stateVariables["/A"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); + + // move point near segment 2 + + let mseg2 = (y2 - y3) / (x2 - x3); + + await core.requestAction({ + actionName: "movePoint", + componentName: `/A`, + args: { x: 0, y: 0.04 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/A"].stateValues.xs[0].tree; + py = stateVariables["/A"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); + + // move point near segment between first and last vertices + + mseg3 = (y4 - y3) / (x4 - x3); + + await core.requestAction({ + actionName: "movePoint", + componentName: `/A`, + args: { x: -10, y: 0.02 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + px = stateVariables["/A"].stateValues.xs[0].tree; + py = stateVariables["/A"].stateValues.xs[1].tree; + + expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); + }); + + it("fixed polyline", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.fixed).eq(true); + + // cannot move vertices + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: [ + [4, 7], + [8, 10], + [1, 9], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + }); + + it("copy propIndex of vertices, dot and array notation", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + + +

+ +

$pl.vertices[$n]{assignNames="P1 P2 P3"}

+ +

$pl.vertex2[$n]{assignNames="x"}

+ +

$pl.vertices[2][$n]{assignNames="xa"}

+ `, + }); + + let t1x = 2, + t1y = -3; + let t2x = 3, + t2y = 4; + let t3x = -3, + t3y = 4; + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"]).eq(undefined); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"]).eq(undefined); + expect(stateVariables["/xa"]).eq(undefined); + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + t1x, + t1y, + ]); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"].stateValues.value.tree).eq(t2x); + expect(stateVariables["/xa"].stateValues.value.tree).eq(t2x); + + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + t2x, + t2y, + ]); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"].stateValues.value.tree).eq(t2y); + expect(stateVariables["/xa"].stateValues.value.tree).eq(t2y); + + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + t3x, + t3y, + ]); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"]).eq(undefined); + expect(stateVariables["/xa"]).eq(undefined); + + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"]).eq(undefined); + expect(stateVariables["/P2"]).eq(undefined); + expect(stateVariables["/P3"]).eq(undefined); + expect(stateVariables["/x"]).eq(undefined); + expect(stateVariables["/xa"]).eq(undefined); + }); + + it("polyline from vector operations", async () => { + let core = await createTestCore({ + doenetML: ` + (-3,2) + + (2,1) + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polyline"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [7, -2], + [6, 3], + [-4, 5], + ]); + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/polyline", + args: { + pointCoords: { 0: [3, 5] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polyline"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [6, 3], + [-4, 5], + ]); + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/polyline", + args: { + pointCoords: { 1: [-9, -6] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polyline"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [-9, -6], + [-9, 2], + ]); + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/polyline", + args: { + pointCoords: { 2: [-3, 1] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/polyline"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [3, 5], + [9, -9], + [-3, 1], + ]); + }); + + it("draggable, vertices draggable", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

draggable:

+

vertices draggable:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + + // cannot move single vertex + + await await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: { 0: [4, 7] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + + // cannot move all vertices + + await await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: [ + [4, 7], + [8, 10], + [1, 9], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([1, 3]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + + // only vertices draggable + + await updateBooleanInputValue({ + boolean: true, + componentName: "/verticesDraggable", + core, + }); + + // can move single vertex + + await await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: { 0: [4, 7] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([4, 7]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); + + // cannot move all vertices + + await await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: [ + [3, 8], + [8, 10], + [1, 9], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([4, 7]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([5, 7]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(false); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); + + // vertices and polyline draggable + + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable", + core, + }); + + // can move single vertex + + await await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: { 1: [-3, 2] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([4, 7]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([-3, 2]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([-2, 6]); + expect(stateVariables["/p"].stateValues.draggable).eq(true); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); + + // can move all vertices + + await await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: [ + [3, 8], + [8, 10], + [1, 9], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([3, 8]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([8, 10]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([1, 9]); + expect(stateVariables["/p"].stateValues.draggable).eq(true); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); + + // polyline but not vertices draggable + + await updateBooleanInputValue({ + boolean: false, + componentName: "/verticesDraggable", + core, + }); + + // cannot move single vertex + + await await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: { 2: [9, 3] }, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([3, 8]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([8, 10]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([1, 9]); + expect(stateVariables["/p"].stateValues.draggable).eq(true); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + + // can move all vertices + + await await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: [ + [-4, 1], + [9, -4], + [0, 7], + ], + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/p"].stateValues.vertices[0].map((x) => x.tree), + ).eqls([-4, 1]); + expect( + stateVariables["/p"].stateValues.vertices[1].map((x) => x.tree), + ).eqls([9, -4]); + expect( + stateVariables["/p"].stateValues.vertices[2].map((x) => x.tree), + ).eqls([0, 7]); + expect(stateVariables["/p"].stateValues.draggable).eq(true); + expect(stateVariables["/p"].stateValues.verticesDraggable).eq(false); + }); + + it("One vertex constrained to grid", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,5) + (-4,-1) + (5,2) + + + + + (-3,4) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 5], + [-4, -1], + [6, 4], + [-3, 4], + ]; + + await testPolylineCopiedTwice({ core, vertices }); + + // move individual vertex + + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move copied polyline up and to the right + + let moveX = 4; + let moveY = 3; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = 1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolylineCopiedTwice({ core, vertices }); + + // try to move double copied polyline down and to the right + + moveX = 1; + moveY = -7; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g3/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = -1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolylineCopiedTwice({ core, vertices }); + }); + + it("Two vertices constrained to same grid", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,5) + + + + + (-4,-1) + (5,2) + + + + + (-3,4) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 4], + [-4, -1], + [6, 4], + [-3, 4], + ]; + + await testPolylineCopiedTwice({ core, vertices }); + + // move individual vertex + + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move copied polyline up and to the right + + let moveX = 4; + let moveY = 3; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = 1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolylineCopiedTwice({ core, vertices }); + + // try to move double copied polyline down and to the right + + moveX = 1; + moveY = -7; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g3/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = -1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolylineCopiedTwice({ core, vertices }); + }); + + it("Three vertices constrained to same grid", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,5) + + + + + (-4,-1) + + + + + (5,2) + + + + + (-3,4) + + + + $(../g1/pg{name="pg"}) + + $g2{name="g3"} + `, + }); + + let vertices = [ + [3, 4], + [-3, 0], + [6, 4], + [-3, 4], + ]; + + await testPolylineCopiedTwice({ core, vertices }); + + // move individual vertex + + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + // adjust for constraint + vertices[1] = [3, 8]; + + await testPolylineCopiedTwice({ core, vertices }); + + // move copied polyline up and to the right + + let moveX = 4; + let moveY = 3; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = 1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolylineCopiedTwice({ core, vertices }); + + // try to move double copied polyline down and to the right + + moveX = 1; + moveY = -7; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g3/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + // adjustment due to constraint + moveX = -1; + moveY = -1; + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await testPolylineCopiedTwice({ core, vertices }); + }); + + it("handle bad vertices", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + // document is created + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pl"]).not.eq(undefined); + }); + + it("length", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

length:

+ `, + }); + + let length = 5 + 2 * Math.sqrt(2) + Math.sqrt(25 + 64); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/length"].stateValues.value).eq(length); + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: { 1: [-8, -4] }, + }, + event: null, + }); + await core.requestAction({ + actionName: "movePolyline", + componentName: "/p", + args: { + pointCoords: { 2: [-8, 2] }, + }, + event: null, + }); + + length = 13 + 6 + Math.sqrt(16 + 64) + Math.sqrt(25 + 64); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/length"].stateValues.value).eq(length); + }); + + // regression test for issue #235 + it("polyline with vertices from mathList/mathInput", async () => { + let core = await createTestCore({ + doenetML: ` + (0,0),(2,2),(-1,5),(-5,1) + $vertexInput + + + + + + $(../g1/pg{name="pg"}) + $pg.vertices{assignNames="v1 v2 v3 v4"} + + $g2{name="g3"} + `, + }); + + let vertices = [ + [0, 0], + [2, 2], + [-1, 5], + [-5, 1], + ]; + + await testPolylineCopiedTwice({ vertices, core }); + + // move individual vertex + vertices[1] = [4, 7]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g1/pg", + args: { + pointCoords: { 1: vertices[1] }, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move copied polyline up and to the right + let moveX = 3; + let moveY = 2; + + for (let i = 0; i < vertices.length; i++) { + vertices[i][0] = vertices[i][0] + moveX; + vertices[i][1] = vertices[i][1] + moveY; + } + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g2/pg", + args: { + pointCoords: vertices, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // move double copied individual vertex + vertices[2] = [-9, -8]; + + await core.requestAction({ + actionName: "movePolyline", + componentName: "/g3/pg", + args: { + pointCoords: { 2: vertices[2] }, + }, + event: null, + }); + + await testPolylineCopiedTwice({ core, vertices }); + + // change last vertices via math input + await updateMathInputValue({ + latex: "(3,2), (-6,5), (4,9), (-2,0)", + componentName: "/vertexInput", + core, + }); + + vertices = [ + [3, 2], + [-6, 5], + [4, 9], + [-2, 0], + ]; + + await testPolylineCopiedTwice({ vertices, core }); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/singlecharactercomponents.test.ts b/packages/doenetml-worker/src/test/tagSpecific/singlecharactercomponents.test.ts new file mode 100644 index 000000000..b2ca29578 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/singlecharactercomponents.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Single character tag tests", async () => { + it("dashes", async () => { + let core = await createTestCore({ + doenetML: ` +

1 2 that's it

+ `, + }); + + // Note these dashes are different unicode even though they display the same here + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq("1 – 2 β€” that's it"); + }); + + it("nbsp", async () => { + let core = await createTestCore({ + doenetML: ` +

actlikeoneword

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq( + "act\u00a0like\u00a0one\u00a0word", + ); + }); + + it("ellipsis", async () => { + let core = await createTestCore({ + doenetML: ` +

we could do that

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq("we could do that…"); + }); + + it("unmatched quotes", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq(`β€β€œβ€™β€˜`); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/text.test.ts b/packages/doenetml-worker/src/test/tagSpecific/text.test.ts new file mode 100644 index 000000000..88174cb86 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/text.test.ts @@ -0,0 +1,938 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputValue, + updateTextInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Text tag tests", async () => { + it("spaces preserved between tags", async () => { + let core = await createTestCore({ + doenetML: ` +

Hello there!

+ +

We could be $_text2.

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("Hello there!"); + expect(stateVariables["/p2"].stateValues.text).eq("We could be there."); + }); + + it("components adapt to text", async () => { + let core = await createTestCore({ + doenetML: ` +

boolean: true

+

number: 5-2

+

math: 5-2

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/text1"].stateValues.value).eq("true"); + expect(stateVariables["/text2"].stateValues.value).eq("3"); + expect(stateVariables["/text3"].stateValues.value).eq("5 - 2"); + }); + + it("text adapts to components", async () => { + let core = await createTestCore({ + doenetML: ` +

number: 4/2

+

number from latex: \\frac{4}{2}

+

number from latex 2: \\frac{4}{2}

+

number latex not parsed as latex: \\frac{4}{2}

+

number does not adapt with convertBoolean: 4/2

+

number multiplies adjacent texts: 54

+

number multiplies adjacent text and string: 54

+

math: sin(2x)

+

math from latex: \\sin(2x)

+

math from latex 2: \\sin(2x)

+

math latex not parsed as latex: \\sin(2x)

+

math multiplies adjacent texts: 54

+

math multiplies adjacent text and string: 54

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n1"].stateValues.value).eq(2); + expect(stateVariables["/n2"].stateValues.value).eq(2); + expect(stateVariables["/n2a"].stateValues.value).eq(2); + expect(stateVariables["/n3"].stateValues.value).eqls(NaN); + expect(stateVariables["/n4"].stateValues.value).eqls(NaN); + expect(stateVariables["/n5"].stateValues.value).eq(20); + expect(stateVariables["/n6"].stateValues.value).eq(20); + + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + expect(stateVariables["/m2a"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["*", 2, "x"], + ]); + + expect(stateVariables["/m3"].stateValues.value.tree).eqls("\uff3f"); + expect(stateVariables["/m4"].stateValues.value.tree).eqls(20); + expect(stateVariables["/m5"].stateValues.value.tree).eqls(20); + }); + + it("text from paragraph components", async () => { + let core = await createTestCore({ + doenetML: ` +

Hello, said the cow. Bye, came the reply. The text attribute of text or text (or text?) doesn't do much.

+ +

$orig.text{assignNames="t"}

+ +

Hello, said the cow. Bye, came the reply. The text attribute of text or text (or text?) doesn't do much.

+ `, + }); + + let theText = `"Hello," said the cow. 'Bye,' came the reply. The text attribute of or (or ?) doesn't do much.`; + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/orig"].stateValues.text).eq(theText); + expect(stateVariables["/textOnly"].stateValues.text).eq(theText); + expect(stateVariables["/insideText"].stateValues.text).eq(theText); + + expect(stateVariables["/t"].stateValues.value).eq(theText); + expect(stateVariables["/t2"].stateValues.value).eq(theText); + }); + + it("text from single character components", async () => { + let core = await createTestCore({ + doenetML: ` +

Pick a number from 1 2 no, maybe from3

+ +

$orig.text{assignNames="t"}

+ +

Pick a number from 1 2 no, maybe from3

+ `, + }); + + const theText = "Pick a β€˜number’ from 1 – 2 β€” no, β€œmaybe” from\u00a03…"; + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/orig"].stateValues.text).eq(theText); + expect(stateVariables["/textOnly"].stateValues.text).eq(theText); + expect(stateVariables["/insideText"].stateValues.text).eq(theText); + + expect(stateVariables["/t"].stateValues.value).eq(theText); + expect(stateVariables["/t2"].stateValues.value).eq(theText); + }); + + it("text does not force composite replacement, even in boolean", async () => { + let core = await createTestCore({ + doenetML: ` + a + + $nothing = + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/b"].stateValues.value).to.be.true; + }); + + it("text in graph", async () => { + let core = await createTestCore({ + doenetML: ` + + $content1 + bye + + +

Anchor 1 coordinates:

+

Anchor 2 coordinates:

+

Change anchor 1 coordinates:

+

Change anchor 2 coordinates:

+

Position from anchor 1: $text1.positionFromAnchor

+

Position from anchor 2: $text2.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

+

Content 1: $text1

+

Content 2: $text2

+

Content 1

+

Content 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["/text1anchor"].stateValues.latex)).eq( + "(1,3)", + ); + expect(cleanLatex(stateVariables["/text2anchor"].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["/pContent1"].stateValues.text).eq( + "Content 1: hello", + ); + expect(stateVariables["/pContent2"].stateValues.text).eq( + "Content 2: bye", + ); + + // move texts by dragging + await core.requestAction({ + actionName: "moveText", + componentName: "/text1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveText", + componentName: "/text2", + args: { x: 4, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "(-2,3)", + ); + expect(cleanLatex(stateVariables["/text2anchor"].stateValues.latex)).eq( + "(4,-5)", + ); + + // move texts 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["/text1anchor"].stateValues.latex)).eq( + "(6,7)", + ); + expect(cleanLatex(stateVariables["/text2anchor"].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 texts by dragging + await core.requestAction({ + actionName: "moveText", + componentName: "/text1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveText", + componentName: "/text2", + args: { x: -8, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "(6,7)", + ); + expect(cleanLatex(stateVariables["/text2anchor"].stateValues.latex)).eq( + "(8,9)", + ); + + // change content of text + await updateTextInputValue({ + text: "hello there", + componentName: "/content1", + core, + }); + await updateTextInputValue({ + text: "bye now", + componentName: "/content2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pContent1"].stateValues.text).eq( + "Content 1: hello there", + ); + expect(stateVariables["/pContent2"].stateValues.text).eq( + "Content 2: bye now", + ); + + // 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: "moveText", + componentName: "/text1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveText", + componentName: "/text2", + args: { x: -8, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "(-10,-9)", + ); + expect(cleanLatex(stateVariables["/text2anchor"].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 text 1 + await updateMathInputValue({ + latex: "(3,4)", + componentName: "/anchorCoords2", + core, + }); + await updateMathInputValue({ + latex: "(1,2)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/text2anchor"].stateValues.latex)).eq( + "(-8,-7)", + ); + + // cannot move texts by dragging + await core.requestAction({ + actionName: "moveText", + componentName: "/text1", + args: { x: 4, y: 6 }, + event: null, + }); + await core.requestAction({ + actionName: "moveText", + componentName: "/text2", + args: { x: 7, y: 8 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "(1,2)", + ); + expect(cleanLatex(stateVariables["/text2anchor"].stateValues.latex)).eq( + "(-8,-7)", + ); + + // can change position from anchor only for math 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", + ); + + // 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 text 1 + await updateMathInputValue({ + latex: "(7,8)", + componentName: "/anchorCoords2", + core, + }); + await updateMathInputValue({ + latex: "(5,6)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "(5,6)", + ); + expect(cleanLatex(stateVariables["/text2anchor"].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 content only for text 1 + await updateTextInputValue({ + text: "hello there again", + componentName: "/content1", + core, + }); + await updateTextInputValue({ + text: "bye now too", + componentName: "/content2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pContent1"].stateValues.text).eq( + "Content 1: hello there again", + ); + expect(stateVariables["/pContent2"].stateValues.text).eq( + "Content 2: bye now", + ); + }); + + it("text in graph, handle bad anchor coordinates", async () => { + let core = await createTestCore({ + doenetML: ` + + Hello + + + +

Anchor 1 coordinates:

+

Change anchor 1 coordinates:

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "x", + ); + + // give good anchor coords + await updateMathInputValue({ + latex: "(6,7)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "(6,7)", + ); + + // give good anchor coords + await updateMathInputValue({ + latex: "(6,7)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "(6,7)", + ); + + // give bad anchor coords again + await updateMathInputValue({ + latex: "q", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/text1anchor"].stateValues.latex)).eq( + "q", + ); + }); + + it("color text via style", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + +

Style number:

+ +

One is $no_style.textStyleDescription, i.e., the text color is $no_style.textColor and the background color is $no_style.backgroundColor.

+

Two is $fixed_style.textStyleDescription, i.e., the text color is $fixed_style.textColor and the background color is $fixed_style.backgroundColor.

+

Three is $variable_style.textStyleDescription, i.e., the text color is $variable_style.textColor and the background color is $variable_style.backgroundColor.

+ + + $no_style{anchor="(1,2)"} + $fixed_style{anchor="(3,4)"} + $variable_style + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/tsd_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/tc_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/bc_no_style"].stateValues.text).eq("none"); + + expect(stateVariables["/tsd_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/tc_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/bc_fixed_style"].stateValues.text).eq("none"); + + expect(stateVariables["/tsd_variable_style"].stateValues.text).eq( + "black", + ); + expect(stateVariables["/tc_variable_style"].stateValues.text).eq( + "black", + ); + expect(stateVariables["/bc_variable_style"].stateValues.text).eq( + "none", + ); + + await updateMathInputValue({ latex: "2", componentName: "/sn", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/tsd_variable_style"].stateValues.text).eq( + "green", + ); + expect(stateVariables["/tc_variable_style"].stateValues.text).eq( + "green", + ); + expect(stateVariables["/bc_variable_style"].stateValues.text).eq( + "none", + ); + + expect(stateVariables["/tsd_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/tc_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/bc_no_style"].stateValues.text).eq("none"); + + expect(stateVariables["/tsd_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/tc_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/bc_fixed_style"].stateValues.text).eq("none"); + + await updateMathInputValue({ latex: "3", componentName: "/sn", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/tsd_variable_style"].stateValues.text).eq( + "red with a blue background", + ); + expect(stateVariables["/tc_variable_style"].stateValues.text).eq("red"); + expect(stateVariables["/bc_variable_style"].stateValues.text).eq( + "blue", + ); + + expect(stateVariables["/tsd_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/tc_no_style"].stateValues.text).eq("black"); + expect(stateVariables["/bc_no_style"].stateValues.text).eq("none"); + + expect(stateVariables["/tsd_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/tc_fixed_style"].stateValues.text).eq("green"); + expect(stateVariables["/bc_fixed_style"].stateValues.text).eq("none"); + }); + + it("text copied by plain macro, but not value, reflects style and anchor position", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + One + Two + + + + + + + $t1{name="t1a"} + $t2{name="t2a"} + + + + + + $t1.value{assignNames="t1b"} + $t2.value{assignNames="t2b"} + + + + +

$t1{name="t1c"} $t2{name="t2c"}

+ +

$t1.value{assignNames="t1d"} $t2.value{assignNames="t2d"}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/t1"].stateValues.value).eq("One"); + expect(stateVariables["/t1a"].stateValues.value).eq("One"); + expect(stateVariables["/t1b"].stateValues.value).eq("One"); + expect(stateVariables["/t1c"].stateValues.value).eq("One"); + expect(stateVariables["/t1d"].stateValues.value).eq("One"); + + expect(stateVariables["/t2"].stateValues.value).eq("Two"); + expect(stateVariables["/t2a"].stateValues.value).eq("Two"); + expect(stateVariables["/t2b"].stateValues.value).eq("Two"); + expect(stateVariables["/t2c"].stateValues.value).eq("Two"); + expect(stateVariables["/t2d"].stateValues.value).eq("Two"); + + expect(stateVariables["/t1"].stateValues.styleNumber).eq(2); + expect(stateVariables["/t1a"].stateValues.styleNumber).eq(2); + expect(stateVariables["/t1b"].stateValues.styleNumber).eq(1); + expect(stateVariables["/t1c"].stateValues.styleNumber).eq(2); + expect(stateVariables["/t1d"].stateValues.styleNumber).eq(1); + expect(stateVariables["/t2"].stateValues.styleNumber).eq(3); + expect(stateVariables["/t2a"].stateValues.styleNumber).eq(3); + expect(stateVariables["/t2b"].stateValues.styleNumber).eq(1); + expect(stateVariables["/t2c"].stateValues.styleNumber).eq(3); + expect(stateVariables["/t2d"].stateValues.styleNumber).eq(1); + + expect(cleanLatex(stateVariables["/t1coords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/t2coords"].stateValues.latex)).eq( + "(3,4)", + ); + expect(cleanLatex(stateVariables["/t1acoords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/t2acoords"].stateValues.latex)).eq( + "(3,4)", + ); + expect(cleanLatex(stateVariables["/t1bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/t2bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + + // move first texts + await core.requestAction({ + actionName: "moveText", + componentName: "/t1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveText", + componentName: "/t2", + args: { x: 4, y: -5 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/t1coords"].stateValues.latex)).eq( + "(-2,3)", + ); + expect(cleanLatex(stateVariables["/t2coords"].stateValues.latex)).eq( + "(4,-5)", + ); + expect(cleanLatex(stateVariables["/t1acoords"].stateValues.latex)).eq( + "(-2,3)", + ); + expect(cleanLatex(stateVariables["/t2acoords"].stateValues.latex)).eq( + "(4,-5)", + ); + expect(cleanLatex(stateVariables["/t1bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/t2bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + + // move second texts + await core.requestAction({ + actionName: "moveText", + componentName: "/t1a", + args: { x: 7, y: 1 }, + event: null, + }); + await core.requestAction({ + actionName: "moveText", + componentName: "/t2a", + args: { x: -8, y: 2 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/t1coords"].stateValues.latex)).eq( + "(7,1)", + ); + expect(cleanLatex(stateVariables["/t2coords"].stateValues.latex)).eq( + "(-8,2)", + ); + expect(cleanLatex(stateVariables["/t1acoords"].stateValues.latex)).eq( + "(7,1)", + ); + expect(cleanLatex(stateVariables["/t2acoords"].stateValues.latex)).eq( + "(-8,2)", + ); + expect(cleanLatex(stateVariables["/t1bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + expect(cleanLatex(stateVariables["/t2bcoords"].stateValues.latex)).eq( + "(0,0)", + ); + + // move third texts + await core.requestAction({ + actionName: "moveText", + componentName: "/t1b", + args: { x: -6, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveText", + componentName: "/t2b", + args: { x: -5, y: -4 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/t1coords"].stateValues.latex)).eq( + "(7,1)", + ); + expect(cleanLatex(stateVariables["/t2coords"].stateValues.latex)).eq( + "(-8,2)", + ); + expect(cleanLatex(stateVariables["/t1acoords"].stateValues.latex)).eq( + "(7,1)", + ); + expect(cleanLatex(stateVariables["/t2acoords"].stateValues.latex)).eq( + "(-8,2)", + ); + expect(cleanLatex(stateVariables["/t1bcoords"].stateValues.latex)).eq( + "(-6,3)", + ); + expect(cleanLatex(stateVariables["/t2bcoords"].stateValues.latex)).eq( + "(-5,-4)", + ); + }); + + it("numCharacters", async () => { + let core = await createTestCore({ + doenetML: ` +

Hello there!

+ +

Number of characters is $t.numCharacters.

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p2"].stateValues.text).eq( + "Number of characters is 11.", + ); + }); +}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/when.cy.js b/packages/doenetml-worker/src/test/tagSpecific/when.test.ts similarity index 56% rename from packages/test-cypress/cypress/e2e/tagSpecific/when.cy.js rename to packages/doenetml-worker/src/test/tagSpecific/when.test.ts index 124f0115d..37f3e2e44 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/when.cy.js +++ b/packages/doenetml-worker/src/test/tagSpecific/when.test.ts @@ -1,18 +1,16 @@ -import { cesc } from "@doenet/utils"; +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateMathInputValue } from "../utils/actions"; -describe("When Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); - it("value, fractionSatisfied, conditionSatisfied are public", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` +describe("When tag tests", async () => { + it("value, fractionSatisfied, conditionSatisfied are public", async () => { + let core = await createTestCore({ + doenetML: ` a - + $n > 0 and $n > 1 @@ -22,42 +20,39 @@ describe("When Tag Tests", function () {

Fraction satisfied: $w.fractionSatisfied{assignNames="fs"}

`, - }, - "*", - ); }); - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); + let stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/v")).should("have.text", "false"); - cy.get(cesc("#\\/cs")).should("have.text", "false"); - cy.get(cesc("#\\/fs")).should("have.text", "0"); + expect(stateVariables["/v"].stateValues.value).eq(false); + expect(stateVariables["/cs"].stateValues.value).eq(false); + expect(stateVariables["/fs"].stateValues.value).eq(0); - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/fs")).should("have.text", "0.5"); - cy.get(cesc("#\\/v")).should("have.text", "false"); - cy.get(cesc("#\\/cs")).should("have.text", "false"); + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/v")).should("have.text", "true"); - cy.get(cesc("#\\/cs")).should("have.text", "true"); - cy.get(cesc("#\\/fs")).should("have.text", "1"); + expect(stateVariables["/v"].stateValues.value).eq(false); + expect(stateVariables["/cs"].stateValues.value).eq(false); + expect(stateVariables["/fs"].stateValues.value).eq(0.5); - cy.get(cesc("#\\/n") + " textarea").type("{home}-{enter}", { - force: true, - }); - cy.get(cesc("#\\/v")).should("have.text", "false"); - cy.get(cesc("#\\/cs")).should("have.text", "false"); - cy.get(cesc("#\\/fs")).should("have.text", "0"); + await updateMathInputValue({ latex: "11", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/v"].stateValues.value).eq(true); + expect(stateVariables["/cs"].stateValues.value).eq(true); + expect(stateVariables["/fs"].stateValues.value).eq(1); + + await updateMathInputValue({ latex: "-11", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/v"].stateValues.value).eq(false); + expect(stateVariables["/cs"].stateValues.value).eq(false); + expect(stateVariables["/fs"].stateValues.value).eq(0); }); - it("fraction satisfied on 2x2 matrix compare", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("fraction satisfied on 2x2 matrix compare", async () => { + let core = await createTestCore({ + doenetML: ` \\begin{pmatrix}1 & 2\\\\ 3 & 4\\end{pmatrix} \\begin{pmatrix}5 & 6\\\\ 7 & 8\\end{pmatrix} \\begin{pmatrix}1 & 6\\\\ 7 & 8\\end{pmatrix} @@ -98,41 +93,34 @@ describe("When Tag Tests", function () {

Fraction satisfied DD:

`, - }, - "*", - ); }); - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); + let stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/fsAA")).should("have.text", "1"); - cy.get(cesc("#\\/fsAB")).should("have.text", "0"); - cy.get(cesc("#\\/fsAC")).should("have.text", "0.25"); - cy.get(cesc("#\\/fsAD")).should("have.text", "0.25"); + expect(stateVariables["/fsAA"].stateValues.value).eq(1); + expect(stateVariables["/fsAB"].stateValues.value).eq(0); + expect(stateVariables["/fsAC"].stateValues.value).eq(0.25); + expect(stateVariables["/fsAD"].stateValues.value).eq(0.25); - cy.get(cesc("#\\/fsBA")).should("have.text", "0"); - cy.get(cesc("#\\/fsBB")).should("have.text", "1"); - cy.get(cesc("#\\/fsBC")).should("have.text", "0.75"); - cy.get(cesc("#\\/fsBD")).should("have.text", "0.25"); + expect(stateVariables["/fsBA"].stateValues.value).eq(0); + expect(stateVariables["/fsBB"].stateValues.value).eq(1); + expect(stateVariables["/fsBC"].stateValues.value).eq(0.75); + expect(stateVariables["/fsBD"].stateValues.value).eq(0.25); - cy.get(cesc("#\\/fsCA")).should("have.text", "0.25"); - cy.get(cesc("#\\/fsCB")).should("have.text", "0.75"); - cy.get(cesc("#\\/fsCC")).should("have.text", "1"); - cy.get(cesc("#\\/fsCD")).should("have.text", "0.5"); + expect(stateVariables["/fsCA"].stateValues.value).eq(0.25); + expect(stateVariables["/fsCB"].stateValues.value).eq(0.75); + expect(stateVariables["/fsCC"].stateValues.value).eq(1); + expect(stateVariables["/fsCD"].stateValues.value).eq(0.5); - cy.get(cesc("#\\/fsDA")).should("have.text", "0.25"); - cy.get(cesc("#\\/fsDB")).should("have.text", "0.25"); - cy.get(cesc("#\\/fsDC")).should("have.text", "0.5"); - cy.get(cesc("#\\/fsDD")).should("have.text", "1"); + expect(stateVariables["/fsDA"].stateValues.value).eq(0.25); + expect(stateVariables["/fsDB"].stateValues.value).eq(0.25); + expect(stateVariables["/fsDC"].stateValues.value).eq(0.5); + expect(stateVariables["/fsDD"].stateValues.value).eq(1); }); - it("fraction satisfied on mismatched size matrix compare", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a + it("fraction satisfied on mismatched size matrix compare", async () => { + let core = await createTestCore({ + doenetML: ` \\begin{pmatrix}1\\end{pmatrix} \\begin{pmatrix}1 & 8\\end{pmatrix} \\begin{pmatrix}1\\\\8\\end{pmatrix} @@ -173,32 +161,28 @@ describe("When Tag Tests", function () {

Fraction satisfied DD:

`, - }, - "*", - ); }); - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); + let stateVariables = await returnAllStateVariables(core); - cy.get(cesc("#\\/fsAA")).should("have.text", "1"); - cy.get(cesc("#\\/fsAB")).should("have.text", "0.5"); - cy.get(cesc("#\\/fsAC")).should("have.text", "0.5"); - cy.get(cesc("#\\/fsAD")).should("have.text", "0.25"); + expect(stateVariables["/fsAA"].stateValues.value).eq(1); + expect(stateVariables["/fsAB"].stateValues.value).eq(0.5); + expect(stateVariables["/fsAC"].stateValues.value).eq(0.5); + expect(stateVariables["/fsAD"].stateValues.value).eq(0.25); - cy.get(cesc("#\\/fsBA")).should("have.text", "0.5"); - cy.get(cesc("#\\/fsBB")).should("have.text", "1"); - cy.get(cesc("#\\/fsBC")).should("have.text", "0.25"); - cy.get(cesc("#\\/fsBD")).should("have.text", "0.25"); + expect(stateVariables["/fsBA"].stateValues.value).eq(0.5); + expect(stateVariables["/fsBB"].stateValues.value).eq(1); + expect(stateVariables["/fsBC"].stateValues.value).eq(0.25); + expect(stateVariables["/fsBD"].stateValues.value).eq(0.25); - cy.get(cesc("#\\/fsCA")).should("have.text", "0.5"); - cy.get(cesc("#\\/fsCB")).should("have.text", "0.25"); - cy.get(cesc("#\\/fsCC")).should("have.text", "1"); - cy.get(cesc("#\\/fsCD")).should("have.text", "0.5"); + expect(stateVariables["/fsCA"].stateValues.value).eq(0.5); + expect(stateVariables["/fsCB"].stateValues.value).eq(0.25); + expect(stateVariables["/fsCC"].stateValues.value).eq(1); + expect(stateVariables["/fsCD"].stateValues.value).eq(0.5); - cy.get(cesc("#\\/fsDA")).should("have.text", "0.25"); - cy.get(cesc("#\\/fsDB")).should("have.text", "0.25"); - cy.get(cesc("#\\/fsDC")).should("have.text", "0.5"); - cy.get(cesc("#\\/fsDD")).should("have.text", "1"); + expect(stateVariables["/fsDA"].stateValues.value).eq(0.25); + expect(stateVariables["/fsDB"].stateValues.value).eq(0.25); + expect(stateVariables["/fsDC"].stateValues.value).eq(0.5); + expect(stateVariables["/fsDD"].stateValues.value).eq(1); }); }); diff --git a/packages/doenetml-worker/src/test/utils/actions.ts b/packages/doenetml-worker/src/test/utils/actions.ts new file mode 100644 index 000000000..71930a5ed --- /dev/null +++ b/packages/doenetml-worker/src/test/utils/actions.ts @@ -0,0 +1,134 @@ +import Core from "../../Core"; + +export async function updateTextInputValue({ + text, + componentName, + core, +}: { + text: string; + componentName: string; + core: Core; +}) { + await core.requestAction({ + componentName, + actionName: "updateImmediateValue", + args: { text }, + event: null, + }); + await core.requestAction({ + componentName, + actionName: "updateValue", + args: {}, + event: null, + }); +} + +export async function updateMathInputValue({ + latex, + componentName, + core, +}: { + latex: string; + componentName: string; + core: Core; +}) { + await core.requestAction({ + componentName, + actionName: "updateRawValue", + args: { rawRendererValue: latex }, + event: null, + }); + await core.requestAction({ + componentName, + actionName: "updateValue", + args: {}, + event: null, + }); +} + +export async function updateMathInputImmediateValue({ + latex, + componentName, + core, +}: { + latex: string; + componentName: string; + core: Core; +}) { + await core.requestAction({ + componentName, + actionName: "updateRawValue", + args: { rawRendererValue: latex }, + event: null, + }); +} + +export async function updateMathInputValueToImmediateValue({ + componentName, + core, +}: { + componentName: string; + core: Core; +}) { + await core.requestAction({ + componentName, + actionName: "updateValue", + args: {}, + event: null, + }); +} + +export async function updateBooleanInputValue({ + boolean, + componentName, + core, +}: { + boolean: boolean; + componentName: string; + core: Core; +}) { + await core.requestAction({ + componentName, + actionName: "updateBoolean", + args: { boolean }, + event: null, + }); +} + +export async function updateMatrixInputValue({ + latex, + componentName, + rowInd, + colInd, + core, + stateVariables, +}: { + latex: string; + componentName: string; + rowInd: number; + colInd: number; + core: Core; + stateVariables: any; +}) { + let matrixInput = stateVariables[componentName]; + let numColumns = matrixInput.stateValues.numColumns; + let childInd = colInd + numColumns * rowInd; + + let matrixInputCellName = + matrixInput.activeChildren[childInd]?.componentName; + + if (matrixInputCellName) { + await core.requestAction({ + componentName: matrixInputCellName, + actionName: "updateRawValue", + args: { rawRendererValue: latex }, + event: null, + }); + await core.requestAction({ + componentName: matrixInputCellName, + actionName: "updateValue", + args: {}, + event: null, + }); + } +} diff --git a/packages/doenetml-worker/src/test/utils/math.ts b/packages/doenetml-worker/src/test/utils/math.ts new file mode 100644 index 000000000..aeb263f10 --- /dev/null +++ b/packages/doenetml-worker/src/test/utils/math.ts @@ -0,0 +1,6 @@ +export function cleanLatex(latex: string) { + return latex + .replace(/\s*/g, "") + .replace(/\\left/g, "") + .replace(/\\right/g, ""); +} diff --git a/packages/doenetml-worker/src/test/utils/test-core.ts b/packages/doenetml-worker/src/test/utils/test-core.ts new file mode 100644 index 000000000..80551957d --- /dev/null +++ b/packages/doenetml-worker/src/test/utils/test-core.ts @@ -0,0 +1,110 @@ +import { createComponentInfoObjects } from "../../utils/componentInfoObjects"; +import { + addDocumentIfItsMissing, + expandDoenetMLsToFullSerializedComponents, +} from "../../utils/expandDoenetML"; +import Core from "../../Core"; + +export async function createTestCore({ doenetML, requestedVariantIndex = 1 }) { + let componentInfoObjects = createComponentInfoObjects(); + + let expandResult = await expandDoenetMLsToFullSerializedComponents({ + doenetMLs: [doenetML], + componentInfoObjects, + }); + + let coreBaseArgs = { + doenetML, + serializedDocument: addDocumentIfItsMissing( + expandResult.fullSerializedComponents[0], + )[0], + flags: {}, + allDoenetMLs: expandResult.allDoenetMLs, + preliminaryErrors: expandResult.errors, + preliminaryWarnings: expandResult.warnings, + componentInfoObjects, + activityId: "", + cid: "", + cidForActivity: "", + pageNumber: 1, + serverSaveId: "", + activityVariantIndex: 1, + requestedVariant: null, + requestedVariantIndex: requestedVariantIndex, + stateVariableChanges: "", + coreId: "", + updateDataOnContentChange: null, + theme: null, + }; + + let core = new Core(coreBaseArgs); + await core.getInitializedPromise(); + + return core; +} + +export async function returnAllStateVariables(core) { + if (!core?.components) { + throw Error("No core or components"); + } + + type CompObj = { + componentName: string; + componentType: string; + stateValues: any; + activeChildren: any[]; + replacements: null | any[]; + replacementsToWithhold: null | any[]; + replacementOf: any; + sharedParameters: any; + }; + let componentsObj: { [key: string]: CompObj } = {}; + for (let componentName in core.components) { + let component = core.components[componentName]; + + let compObj: CompObj = { + componentName, + componentType: component.componentType, + stateValues: {}, + activeChildren: [], + replacements: null, + replacementsToWithhold: null, + replacementOf: null, + sharedParameters: null, + }; + + for (let vName in component.state) { + compObj.stateValues[vName] = await component.state[vName].value; + } + compObj.activeChildren = component.activeChildren.map((x) => + x.componentName + ? { + componentName: x.componentName, + componentType: x.componentType, + } + : x, + ); + if (component.replacements) { + compObj.replacements = component.replacements.map((x) => + x.componentName + ? { + componentName: x.componentName, + componentType: x.componentType, + } + : x, + ); + if (component.replacementsToWithhold !== undefined) { + compObj.replacementsToWithhold = + component.replacementsToWithhold; + } + } + if (component.replacementOf) { + compObj.replacementOf = component.replacementOf.componentName; + } + compObj.sharedParameters = component.sharedParameters; + + componentsObj[componentName] = compObj; + } + + return componentsObj; +} diff --git a/packages/doenetml-worker/src/utils/math.ts b/packages/doenetml-worker/src/utils/math.ts index 022820806..863eb4c76 100644 --- a/packages/doenetml-worker/src/utils/math.ts +++ b/packages/doenetml-worker/src/utils/math.ts @@ -417,6 +417,7 @@ export function normalizeLatexString( ["\u2212", "-"], // minus sign ["\u22C5", " \\cdot "], // dot operator ["\u00B7", " \\cdot "], // middle dot + ["\u00D7", " \\times "], // times operator ["\u222A", " \\cup "], // βˆͺ ["\u2229", " \\cap "], // ∩ ["\u221E", " \\infty "], // ∞ diff --git a/packages/doenetml-worker/src/utils/text.js b/packages/doenetml-worker/src/utils/text.js deleted file mode 100644 index a7488224e..000000000 --- a/packages/doenetml-worker/src/utils/text.js +++ /dev/null @@ -1,147 +0,0 @@ -export function textFromComponent(component) { - if (typeof component !== "object") { - return component.toString(); - } else if (typeof component.stateValues.text === "string") { - return component.stateValues.text; - } else { - return " "; - } -} - -// Concatenate the text from children into one string. -// Add commas between the components that are all from one composite -// if that composite has asList set to true -export function textFromChildren( - children, - textFromComponentConverter = textFromComponent, -) { - let result = textFromChildrenSub({ - compositeReplacementRange: children.compositeReplacementRange, - children, - startInd: 0, - endInd: children.length - 1, - textFromComponentConverter, - }); - - return result.newChildren.map(textFromComponentConverter).join(""); -} - -function textFromChildrenSub({ - compositeReplacementRange, - children, - startInd, - endInd, - textFromComponentConverter, - potentialListComponents = null, -}) { - let newChildren = []; - let newPotentialListComponents = []; - let lastChildInd = startInd - 1; - - for ( - let rangeInd = 0; - rangeInd < compositeReplacementRange.length; - rangeInd++ - ) { - let range = compositeReplacementRange[rangeInd]; - - let rangeFirstInd = range.firstInd; - let rangeLastInd = range.lastInd; - - if (rangeFirstInd > lastChildInd && rangeLastInd <= endInd) { - if (lastChildInd + 1 < rangeFirstInd) { - // don't process these children, so just add them back to newChildren - newChildren.push( - ...children.slice(lastChildInd + 1, rangeFirstInd), - ); - if (potentialListComponents) { - // Since we didn't change the components, - // their status of being a potential list component is not changed - newPotentialListComponents.push( - ...potentialListComponents.slice( - lastChildInd - startInd + 1, - rangeFirstInd - startInd, - ), - ); - } - } - - // If a composite produced composites that produced children, - // then this outer composite is first in the array of replacement ranges. - // We first process the children corresponding to any of these replacement composites, - // which will concatenate the replacements of each composite into a single text, - // which may be be turned into a list according to the settings of that composite. - - // We remove the replacement range of the current composite (any all earlier ones) - let subReplacementRange = compositeReplacementRange.slice( - rangeInd + 1, - ); - - let { - newChildren: childrenInRange, - newPotentialListComponents: potentialListComponentsInRange, - } = textFromChildrenSub({ - compositeReplacementRange: subReplacementRange, - children, - startInd: rangeFirstInd, - endInd: rangeLastInd, - textFromComponentConverter, - potentialListComponents: range.potentialListComponents, - }); - - let allAreListComponents = potentialListComponentsInRange.every( - (x) => x, - ); - - if ( - range.asList && - allAreListComponents && - childrenInRange.length > 1 - ) { - // add commas between all children from a single composite - // (after converting them into strings) - // triming any white space to the right of all but the last child - // so that there is not a space before each comma - newChildren.push( - childrenInRange - .map(textFromComponentConverter) - .filter((v) => v.trim() !== "") - .map((v, i, a) => - i === a.length - 1 ? v : v.trimEnd(), - ) - .join(", "), - ); - } else { - // We are not turning the children in a list, - // so just convert the children into strings and concatentate - newChildren.push( - childrenInRange.map(textFromComponentConverter).join(""), - ); - } - - if (potentialListComponents) { - // record whether the result from the composite (a single string now) - // should be considered a list component for any outer composite - newPotentialListComponents.push(allAreListComponents); - } - lastChildInd = rangeLastInd; - } - } - - if (lastChildInd < endInd) { - // don't process these children, so just add them back to newChildren - newChildren.push(...children.slice(lastChildInd + 1, endInd + 1)); - if (potentialListComponents) { - // Since we didn't change the components, - // their status of being a potential list component is not changed - newPotentialListComponents.push( - ...potentialListComponents.slice( - lastChildInd - startInd + 1, - endInd - startInd + 1, - ), - ); - } - } - - return { newChildren, newPotentialListComponents }; -} diff --git a/packages/doenetml-worker/src/utils/text.ts b/packages/doenetml-worker/src/utils/text.ts new file mode 100644 index 000000000..3d66ab422 --- /dev/null +++ b/packages/doenetml-worker/src/utils/text.ts @@ -0,0 +1,170 @@ +export function textFromComponent(component: any): string { + if (typeof component !== "object") { + return component.toString(); + } else if (component.stateValues.hidden) { + return ""; + } else if (typeof component.stateValues.text === "string") { + return component.stateValues.text; + } else { + return " "; + } +} + +// Concatenate the text from children into one string. +// Add commas between the components that are all from one composite +// if that composite has asList set to true +export function textFromChildren( + children: any, + textFromComponentConverter = textFromComponent, +) { + let result = textFromChildrenSub({ + compositeReplacementRange: children.compositeReplacementRange, + children, + startInd: 0, + endInd: children.length - 1, + textFromComponentConverter, + }); + + return result.newChildren.map(textFromComponentConverter).join(""); +} + +function textFromChildrenSub({ + compositeReplacementRange, + children, + startInd, + endInd, + textFromComponentConverter, + potentialListComponents, +}: { + compositeReplacementRange: { + firstInd: number; + lastInd: number; + asList: boolean; + hidden: boolean; + potentialListComponents: boolean[]; + }[]; + children: any; + startInd: number; + endInd: number; + textFromComponentConverter: ( + value: any, + index: number, + array: any[], + ) => string; + potentialListComponents?: boolean[]; +}) { + let newChildren: any[] = []; + let newPotentialListComponents: boolean[] = []; + let lastChildInd = startInd - 1; + + for ( + let rangeInd = 0; + rangeInd < compositeReplacementRange.length; + rangeInd++ + ) { + let range = compositeReplacementRange[rangeInd]; + + let rangeFirstInd = range.firstInd; + let rangeLastInd = range.lastInd; + + if (rangeFirstInd > lastChildInd && rangeLastInd <= endInd) { + if (lastChildInd + 1 < rangeFirstInd) { + // don't process these children, so just add them back to newChildren + newChildren.push( + ...children.slice(lastChildInd + 1, rangeFirstInd), + ); + if (potentialListComponents) { + // Since we didn't change the components, + // their status of being a potential list component is not changed + newPotentialListComponents.push( + ...potentialListComponents.slice( + lastChildInd - startInd + 1, + rangeFirstInd - startInd, + ), + ); + } + } + + if (!range.hidden) { + // If a composite produced composites that produced children, + // then this outer composite is first in the array of replacement ranges. + // We first process the children corresponding to any of these replacement composites, + // which will concatenate the replacements of each composite into a single text, + // which may be be turned into a list according to the settings of that composite. + + // We remove the replacement range of the current composite (any all earlier ones) + let subReplacementRange = compositeReplacementRange.slice( + rangeInd + 1, + ); + + let { + newChildren: childrenInRange, + newPotentialListComponents: potentialListComponentsInRange, + } = textFromChildrenSub({ + compositeReplacementRange: subReplacementRange, + children, + startInd: rangeFirstInd, + endInd: rangeLastInd, + textFromComponentConverter, + potentialListComponents: range.potentialListComponents, + }); + + let allAreListComponents = potentialListComponentsInRange.every( + (x) => x, + ); + + if ( + range.asList && + allAreListComponents && + childrenInRange.length > 1 + ) { + // add commas between all children from a single composite + // (after converting them into strings) + // trimming any white space to the right of all but the last child + // so that there is not a space before each comma + newChildren.push( + childrenInRange + .map(textFromComponentConverter) + .filter((v) => v.trim() !== "") + .map((v, i, a) => + i === a.length - 1 ? v : v.trimEnd(), + ) + .join(", "), + ); + } else { + // We are not turning the children in a list, + // so just convert the children into strings and concatentate + newChildren.push( + childrenInRange + .map(textFromComponentConverter) + .join(""), + ); + } + + if (potentialListComponents) { + // record whether the result from the composite (a single string now) + // should be considered a list component for any outer composite + newPotentialListComponents.push(allAreListComponents); + } + } + lastChildInd = rangeLastInd; + } + } + + if (lastChildInd < endInd) { + // don't process these children, so just add them back to newChildren + newChildren.push(...children.slice(lastChildInd + 1, endInd + 1)); + if (potentialListComponents) { + // Since we didn't change the components, + // their status of being a potential list component is not changed + newPotentialListComponents.push( + ...potentialListComponents.slice( + lastChildInd - startInd + 1, + endInd - startInd + 1, + ), + ); + } + } + + return { newChildren, newPotentialListComponents }; +} diff --git a/packages/doenetml/package.json b/packages/doenetml/package.json index cebe06ec0..2ce7c922b 100644 --- a/packages/doenetml/package.json +++ b/packages/doenetml/package.json @@ -81,16 +81,13 @@ "idb-keyval": "^6.2.1", "json-stringify-deterministic": "^1.0.12", "lorem-ipsum": "^2.0.8", - "math-expressions": "^2.0.0-alpha66", "nanoid": "^4.0.2", "prismjs": "^1.29.0", - "react-copy-to-clipboard": "^5.0.3", + "react-copy-to-clipboard": "^5.1.0", "react-icons": "^4.12.0", "react-mathquill": "^1.0.3", "react-measure": "^2.5.2", - "react-router": "^6.23.1", - "react-router-dom": "^6.23.1", - "react-simple-code-editor": "^0.13.1", + "react-router": "^6.26.2", "react-visibility-sensor-v2": "^1.0.0", "recoil": "^0.7.7", "styled-components": "^5.3.11" diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/answer.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/answer.cy.js index 8d185a051..ac33fcbc3 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/answer.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/answer.cy.js @@ -6,16 +6,16 @@ describe("Answer Tag Tests", function () { cy.visit("/"); }); - it("answer sugar from one string", () => { + it("integrated submit buttons", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

x+y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

+

+ x+y + x+z +

`, }, "*", @@ -31,942 +31,278 @@ describe("Answer Tag Tests", function () { .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.log("Test value displayed in browser"); // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); cy.log("Type correct answer in"); - - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); + cy.get(mathinputAnchor).type(`x+y`, { force: true }); // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Press enter to submit"); + cy.log("Press enter"); cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Add space"); + cy.get(mathinputAnchor).type(`{end} `, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+yz'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); + cy.log("Press enter"); + cy.get(mathinputAnchor).type(`{enter}`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+y'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - }); - }); + cy.log("Delete space"); + cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+yz'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - it("answer sugar from one macro", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x+y -

$xy

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); + cy.log("Press enter"); + cy.get(mathinputAnchor).type(`{enter}`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+y'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.log("Add letter"); + cy.get(mathinputAnchor).type(`{end}z`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+yz'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + cy.log("Delete letter (no longer goes back to saying correct)"); + cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+y'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); + cy.log("Delete more"); + cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}`, { + force: true, }); + // cy.get(mathinputAnchor).should('have.value', 'x'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Type correct answer in"); - - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); + cy.log("Back to correct (no longer goes back to saying correct)"); + cy.get(mathinputAnchor).type(`{end}+y`, { force: true }); // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Press enter to submit"); + cy.log("Press enter"); cy.get(mathinputAnchor).type(`{enter}`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+y'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - // wrap to change value of cesc('#\\/sr1') - cy.window().then(async (win) => { - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should( - "have.text", - "x+y", - ); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues - .currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues - .submittedResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables[mathinputName].stateValues.value, - ).eqls(["+", "x", "y"]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues - .currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues - .submittedResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables[mathinputName].stateValues.value, - ).eqls("x"); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues - .currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues - .submittedResponses, - ).eqls(["x"]); - expect( - stateVariables[mathinputName].stateValues.value, - ).eqls("x"); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); + cy.log("Delete again"); + cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}`, { + force: true, }); - }); - }); + // cy.get(mathinputAnchor).should('have.value', 'x'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - it("answer sugar from one math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); + cy.log("Press enter on submit button"); + cy.get(mathinputSubmitAnchor).type(`{enter}`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.log("Add letter"); + cy.get(mathinputAnchor).type(`{end}a`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'xa'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + cy.log("Delete letter (no longer goes back to saying incorrect)"); + cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); + cy.log("Delete all"); + cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Type correct answer in"); + cy.log( + "Restore incorrect submitted answer (no longer goes back to saying incorrect)", + ); + cy.get(mathinputAnchor).type(`x`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); + cy.log("Click submit button"); + cy.get(mathinputSubmitAnchor).click(); + // cy.get(mathinputAnchor).should('have.value', 'x'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - // wrap to change value of cesc('#\\/sr1') - cy.window().then(async (win) => { - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should( - "have.text", - "x+y", - ); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues - .currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues - .submittedResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables[mathinputName].stateValues.value, - ).eqls(["+", "x", "y"]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Enter partially correct answer"); + cy.get(mathinputAnchor).type(`{end}+z`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+z'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues - .currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues - .submittedResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables[mathinputName].stateValues.value, - ).eqls("x"); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Click submit button"); + cy.get(mathinputSubmitAnchor).click(); + // cy.get(mathinputAnchor).should('have.value', 'x+z'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("have.text", "32 %"); - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues - .currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues - .submittedResponses, - ).eqls(["x"]); - expect( - stateVariables[mathinputName].stateValues.value, - ).eqls("x"); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - }); - }); - }); + cy.log("Add letter"); + cy.get(mathinputAnchor).type(`{end}z`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+zz'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - it("answer sugar from macros and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - xy -

$x+$y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", + cy.log( + "Delete letter (no longer goes back to saying partially correct)", ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); + cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+z'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); + cy.log("Delete more"); + cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}`, { + force: true, }); + // cy.get(mathinputAnchor).should('have.value', 'x'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); + cy.log( + "Back to partial (no longer goes back to saying partially correct)", + ); + cy.get(mathinputAnchor).type(`{end}+z`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+z'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); + cy.log("Click submit button"); + cy.get(mathinputSubmitAnchor).click(); + // cy.get(mathinputAnchor).should('have.value', 'x+z'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("have.text", "32 %"); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Enter invalid answer"); + cy.get(mathinputAnchor).type(`{end}/`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+z'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); + cy.log("Click submit button"); + cy.get(mathinputSubmitAnchor).click(); + // cy.get(mathinputAnchor).should('have.value', 'x+z/'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Another invalid answer shows submit button again"); + cy.get(mathinputAnchor).type(`{end}^`, { force: true }); + // cy.get(mathinputAnchor).should('have.value', 'x+z/^'); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + cy.get(mathinputPartialAnchor).should("not.exist"); - cy.log("Submit answer"); + cy.log("Click submit button"); cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); + // cy.get(mathinputAnchor).should('have.value', 'x+z/^'); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); + cy.get(mathinputPartialAnchor).should("not.exist"); }); }); - it("answer sugar from maths and string", () => { + it("integrated submit buttons, text", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

x+y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

+

+ hello there + bye +

`, }, "*", @@ -977,462 +313,233 @@ describe("Answer Tag Tests", function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = + let textinputName = stateVariables["/_answer1"].stateValues.inputChildren[0] .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + let textinputAnchor = cesc2("#" + textinputName + "_input"); + let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); + let textinputCorrectAnchor = cesc2( + "#" + textinputName + "_correct", + ); + let textinputIncorrectAnchor = cesc2( + "#" + textinputName + "_incorrect", + ); + let textinputPartialAnchor = cesc2( + "#" + textinputName + "_partial", + ); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.get(textinputAnchor).should("have.value", ""); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); cy.log("Type correct answer in"); + cy.get(textinputAnchor).type(`hello there`); + cy.get(textinputAnchor).should("have.value", "hello there"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.log("Press enter"); + cy.get(textinputAnchor).type(`{enter}`); + cy.get(textinputAnchor).should("have.value", "hello there"); + cy.get(textinputSubmitAnchor).should("not.exist"); + cy.get(textinputCorrectAnchor).should("be.visible"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); + cy.log("Add letter"); + cy.get(textinputAnchor).type(`z`); + cy.get(textinputAnchor).should("have.value", "hello therez"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); + cy.log("Delete letter (no longer goes back to saying correct)"); + cy.get(textinputAnchor).type(`{backspace}`); + cy.get(textinputAnchor).should("have.value", "hello there"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Delete more"); + cy.get(textinputAnchor).type(`{backspace}{backspace}`); + cy.get(textinputAnchor).should("have.value", "hello the"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); + cy.log("Back to correct"); + cy.get(textinputAnchor).type(`re`); + cy.get(textinputAnchor).should("have.value", "hello there"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Press enter"); + cy.get(textinputAnchor).type(`{enter}`); + cy.get(textinputAnchor).should("have.value", "hello there"); + cy.get(textinputSubmitAnchor).should("not.exist"); + cy.get(textinputCorrectAnchor).should("be.visible"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); + cy.log("Add a space"); + cy.get(textinputAnchor).type(` `); + cy.get(textinputAnchor).should("have.value", "hello there "); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - }); - }); + cy.log("Press enter"); + cy.get(textinputAnchor).type(`{enter}`); + cy.get(textinputAnchor).should("have.value", "hello there "); + cy.get(textinputSubmitAnchor).should("not.exist"); + cy.get(textinputCorrectAnchor).should("be.visible"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - it("answer sugar from math, macro, and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - y -

x+$y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); + cy.log("Delete again"); + cy.get(textinputAnchor).type(`{backspace}{backspace}{backspace}`); + cy.get(textinputAnchor).should("have.value", "hello the"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.log("Press enter on submit button"); + cy.get(textinputSubmitAnchor).type(`{enter}`, { force: true }); + cy.get(textinputAnchor).should("have.value", "hello the"); + cy.get(textinputSubmitAnchor).should("not.exist"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("be.visible"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + cy.log("Add letter"); + cy.get(textinputAnchor).type(`a`); + cy.get(textinputAnchor).should("have.value", "hello thea"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.log("Delete letter (no longer goes back to saying incorrect)"); + cy.get(textinputAnchor).type(`{backspace}`); + cy.get(textinputAnchor).should("have.value", "hello the"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Type correct answer in"); + cy.log("Delete all"); + cy.get(textinputAnchor).clear(); + cy.get(textinputAnchor).should("have.value", ""); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); + cy.log( + "Restore incorrect submitted answer (no longer goes back to saying incorrect)", + ); + cy.get(textinputAnchor).type(`hello the`); + cy.get(textinputAnchor).should("have.value", "hello the"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.log("Press enter"); + cy.get(textinputAnchor).type(`{enter}`); + cy.get(textinputAnchor).should("have.value", "hello the"); + cy.get(textinputSubmitAnchor).should("not.exist"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("be.visible"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); + cy.log("Enter partially correct answer"); + cy.get(textinputAnchor).clear().type(`bye`); + cy.get(textinputAnchor).should("have.value", "bye"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); + cy.log("Click submit button"); + cy.get(textinputSubmitAnchor).click(); + cy.get(textinputAnchor).should("have.value", "bye"); + cy.get(textinputSubmitAnchor).should("not.exist"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("have.text", "32 %"); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Add letter"); + cy.get(textinputAnchor).type(`z`); + cy.get(textinputAnchor).should("have.value", "byez"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); + cy.log( + "Delete letter (no longer goes back to saying partially correct)", + ); + cy.get(textinputAnchor).type(`{backspace}`); + cy.get(textinputAnchor).should("have.value", "bye"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.log("Delete more"); + cy.get(textinputAnchor).type(`{backspace}{backspace}`); + cy.get(textinputAnchor).should("have.value", "b"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); + cy.log( + "Back to partial (no longer goes back to saying partially correct)", + ); + cy.get(textinputAnchor).type(`ye`); + cy.get(textinputAnchor).should("have.value", "bye"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); + cy.log("Click submit button"); + cy.get(textinputSubmitAnchor).click(); + cy.get(textinputAnchor).should("have.value", "bye"); + cy.get(textinputSubmitAnchor).should("not.exist"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); + cy.get(textinputPartialAnchor).should("have.text", "32 %"); }); }); - it("answer sugar from one string, set to text", () => { + it("submit buttons with two answer blanks", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

+

Enter values that sum to 3x: + + $_mathinput1.immediateValue{isResponse}+$_mathinput2.immediateValue{isResponse} = 3x + $_mathinput1.immediateValue+$_mathinput2.immediateValue = 3 +

+

$_mathinput1.immediateValue

+

$_mathinput2.immediateValue

`, }, "*", @@ -1441,643 +548,311 @@ describe("Answer Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Test value displayed in browser"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Enter correct answer"); + cy.get(cesc("#\\/_mathinput1") + " textarea").type(`x+y`, { + force: true, + }); + cy.get(cesc("#\\/_mathinput2") + " textarea").type(`2x-y`, { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_mathinput2") + " textarea").blur(); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("correct"); }); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Type letter in input1"); + cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}z", { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Delete letter (no longer goes back to saying correct)"); + cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}{backspace}", { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); + cy.log("Type letter in input2"); + cy.get(cesc("#\\/_mathinput1") + " textarea").blur(); + cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}q", { + force: true, }); - }); - - it("answer sugar from one string, set to text, expanded", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

+ cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); + }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - `, - }, - "*", - ); + cy.log("Delete letter (no longer goes back to saying correct)"); + cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}{backspace}", { + force: true, }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("correct"); }); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Pressing enter does not submit"); - cy.get(textinputAnchor).type(`{enter}`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there \n"); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there \n"); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there \n"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there \n", - ); + cy.log("Type letter in input1"); + cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}z", { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there \n"); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there \n"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there \n"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there \n"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there \n"]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there \n", - ); + cy.log("Type letter in input2"); + cy.get(cesc("#\\/_mathinput1") + " textarea").blur(); + cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}q", { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there \n"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there \n"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Delete letter in input1"); + cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}{backspace}", { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Don't go back to saying correct if return to previous answer"); + cy.get(cesc("#\\/_mathinput1") + " textarea").blur(); + cy.get(cesc("#\\/_mathinput2") + " textarea") + .type("{end}{backspace}", { force: true }) + .blur(); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("correct"); }); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.log("Enter partially correct answer"); + cy.get(cesc("#\\/_mathinput1") + " textarea") + .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) + .blur(); + cy.get(cesc("#\\/_mathinput2") + " textarea") + .type(`{ctrl+home}{shift+end}{backspace}3-x`, { force: true }) + .blur(); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("50% correct"); }); - }); - }); - - it("answer sugar from one macro, set to text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - hello there -

$h

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); + cy.log("Delete letter in input1"); + cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}{backspace}", { + force: true, }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log( + "Add letter back (no longer goes back to saying partially correct)", + ); + cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}x", { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("50% correct"); }); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Enter incorrect answer"); + cy.get(cesc("#\\/_mathinput1") + " textarea") + .type(`{end}{backspace}y`, { force: true }) + .blur(); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).type("{enter}", { force: true }); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("incorrect"); }); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Delete letter in input2"); + cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}{backspace}", { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - }); + cy.log("Add letter back (no longer goes back to saying incorrect)"); + cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}x", { + force: true, + }); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); + }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); + + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).type("{enter}", { force: true }); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("incorrect"); + }); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); }); - it("answer sugar from one text", () => { + it("submit buttons with two text answer blanks", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- + a +

Enter rain and snow in either order: + + $_textinput1.immediateValue{isResponse} $_textinput2.immediateValue{isResponse} = rain snow + $_textinput1.immediateValue $_textinput2.immediateValue = snow rain + $_textinput1.immediateValue = rain + $_textinput1.immediateValue = snow + $_textinput2.immediateValue = rain + $_textinput2.immediateValue = snow +

`, }, "*", @@ -2086,619 +861,307 @@ describe("Answer Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); + cy.log("Test value displayed in browser"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", ""); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", ""); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Enter a correct answer"); + cy.get(cesc("#\\/_textinput1_input")).type(`rain`); + cy.get(cesc("#\\/_textinput2_input")).type(`snow`).blur(); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("correct"); }); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Type letter in input1"); + cy.get(cesc("#\\/_textinput1_input")).type("z"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rainz"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Delete letter (no longer goes back to saying correct)"); + cy.get(cesc("#\\/_textinput1_input")).type("{backspace}"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Type letter in input2"); + cy.get(cesc("#\\/_textinput1_input")).blur(); + cy.get(cesc("#\\/_textinput2_input")).type("q"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snowq"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Delete letter (no longer goes back to saying correct)"); + cy.get(cesc("#\\/_textinput2_input")).type("{backspace}"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); - }); - }); - - it("answer sugar from one copy with createComponentOfType text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - hello there -

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); + cy.log("Type letter in input1"); + cy.get(cesc("#\\/_textinput1_input")).type("z"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rainz"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Type letter in input2"); + cy.get(cesc("#\\/_textinput2_input")).type("q"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rainz"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snowq"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Delete letter in input1"); + cy.get(cesc("#\\/_textinput1_input")).type("{backspace}"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snowq"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Don't go back to saying correct if return to previous answer"); + cy.get(cesc("#\\/_textinput2_input")).type("{backspace}").blur(); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("correct"); }); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Enter partially correct answer"); + cy.get(cesc("#\\/_textinput1_input")).clear().type(`x`).blur(); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("50% correct"); + }); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Delete letter in input2"); + cy.get(cesc("#\\/_textinput2_input")).type("{backspace}"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "sno"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); - }); - }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - it("answer sugar from one macro with createComponentOfType text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - hello there -

$(h{createComponentOfType="text"})

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); + cy.log( + "Add letter back (no longer to back to saying partially correct)", + ); + cy.get(cesc("#\\/_textinput2_input")).type("w"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).click(); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("50% correct"); }); - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.log("Enter incorrect answer"); + cy.get(cesc("#\\/_textinput2_input")).clear().type(`y`).blur(); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "y"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).type("{enter}", { force: true }); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "y"); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("incorrect"); }); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.log("Delete letter in input2"); + cy.get(cesc("#\\/_textinput2_input")).type("{backspace}"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", ""); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Add letter back (no longer go back to saying incorrect"); + cy.get(cesc("#\\/_textinput2_input")).type("y"); + cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); + cy.get(cesc("#\\/_textinput2_input")).should("have.value", "y"); + cy.get(cesc("#\\/_answer1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); }); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.log("Submit answer"); + cy.get(cesc("#\\/_answer1_submit")).type("{enter}", { force: true }); + cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); + cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); + cy.get(cesc("#\\/_answer1_incorrect")) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("incorrect"); }); - }); + cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); }); - it("answer sugar from macro and string, set to text", () => { + it("submit button with external inputs", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - hello -

$h there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- + a +

Favorite variable:

+

Second favorite variable:

+

Enter variable: + + + $ans.immediatevalue{isResponse} = $var.immediatevalue + $ans.immediatevalue = $var2.immediatevalue + +

`, }, "*", @@ -2707,411 +1170,163 @@ describe("Answer Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); + // cy.get(cesc('#\\/var') + ' textarea').should('have.value', 'x'); + // cy.get(cesc('#\\/var2') + ' textarea').should('have.value', 'y'); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', ''); + cy.get(cesc("#\\/ans_submit")).should("be.visible"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); + cy.log("Type correct answer in"); + cy.get(cesc("#\\/ans") + " textarea").type(`x`, { force: true }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'x'); + cy.get(cesc("#\\/ans_submit")).should("be.visible"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); + cy.log("Press enter"); + cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'x'); + cy.get(cesc("#\\/ans_submit")).should("not.exist"); + cy.get(cesc("#\\/ans_correct")).should("be.visible"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); + cy.log("Change correct answer"); + cy.get(cesc("#\\/var") + " textarea").type(`{end}{backspace}u{enter}`, { + force: true, + }); + // cy.get(cesc('#\\/var') + ' textarea').should('have.value', 'u'); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'x'); + cy.get(cesc("#\\/ans_submit")).should("be.visible"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); + cy.log("Press enter"); + cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'x'); + cy.get(cesc("#\\/ans_submit")).should("not.exist"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("be.visible"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.log("Change to new correct answer"); + cy.get(cesc("#\\/ans") + " textarea").type(`{end}{backspace}u`, { + force: true, + }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'u'); + cy.get(cesc("#\\/ans_submit")).should("be.visible"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); + cy.log("Press enter"); + cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'u'); + cy.get(cesc("#\\/ans_submit")).should("not.exist"); + cy.get(cesc("#\\/ans_correct")).should("be.visible"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); + cy.log("Change partial credit answer"); + cy.get(cesc("#\\/var2") + " textarea").type( + `{end}{backspace}v{enter}`, + { + force: true, + }, + ); + // cy.get(cesc('#\\/var2') + ' textarea').should('have.value', 'v'); + // cy.get(cesc('#\\/var') + ' textarea').should('have.value', 'u'); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'u'); + cy.get(cesc("#\\/ans_submit")).should("be.visible"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.log("Press enter"); + cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'u'); + cy.get(cesc("#\\/ans_submit")).should("not.exist"); + cy.get(cesc("#\\/ans_correct")).should("be.visible"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); + cy.log("Change to new partial correct answer"); + cy.get(cesc("#\\/ans") + " textarea").type(`{end}{backspace}v`, { + force: true, }); - }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'v'); + cy.get(cesc("#\\/ans_submit")).should("be.visible"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - it("answer sugar from text and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

+ cy.log("Press enter"); + cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'v'); + cy.get(cesc("#\\/ans_submit")).should("not.exist"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("be.visible"); - `, - }, - "*", - ); + cy.log("Change correct answer"); + cy.get(cesc("#\\/var") + " textarea").type(`{end}{backspace}w{enter}`, { + force: true, }); + // cy.get(cesc('#\\/var') + ' textarea').should('have.value', 'w'); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'v'); + // cy.get(cesc('#\\/var2') + ' textarea').should('have.value', 'v'); + cy.get(cesc("#\\/ans_submit")).should("be.visible"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.log("Press enter"); + cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'v'); + cy.get(cesc("#\\/ans_submit")).should("not.exist"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("be.visible"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); + cy.log("Change to new correct answer"); + cy.get(cesc("#\\/ans") + " textarea").type(`{end}{backspace}w`, { + force: true, }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'w'); + cy.get(cesc("#\\/ans_submit")).should("be.visible"); + cy.get(cesc("#\\/ans_correct")).should("not.exist"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); + + cy.log("Press enter"); + cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); + // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'w'); + cy.get(cesc("#\\/ans_submit")).should("not.exist"); + cy.get(cesc("#\\/ans_correct")).should("be.visible"); + cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); + cy.get(cesc("#\\/ans_partial")).should("not.exist"); }); - it("answer sugar from macros and string, does not ignore blank string, set to text", () => { + // actually test the interface of block versus inline choice inputs + + it("switch answer between inline and block", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - hellothere -

$h $t

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- + a +

Inline:

+ + + cat + dog + monkey + + `, }, "*", @@ -3122,204 +1337,116 @@ describe("Answer Tag Tests", function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let textinputName = + let choiceinputName = cesc2( stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); + .componentName, + ); + let choiceinputAnchor = "#" + choiceinputName; + let choiceinputSubmitAnchor = "#" + choiceinputName + "_submit"; + let choiceinputCorrectAnchor = "#" + choiceinputName + "_correct"; + let choiceinputIncorrectAnchor = + "#" + choiceinputName + "_incorrect"; + let choiceinputPartialAnchor = "#" + choiceinputName + "_partial"; - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); + cy.get(choiceinputAnchor).should("have.value", ""); + cy.get(choiceinputSubmitAnchor) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); + }); + cy.get(choiceinputCorrectAnchor).should("not.exist"); + cy.get(choiceinputIncorrectAnchor).should("not.exist"); + cy.get(choiceinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); + cy.log("toggle inline"); + cy.get(cesc("#\\/inline")).click(); + cy.get(`${choiceinputAnchor} option:nth-of-type(3)`).should( + "be.visible", + ); + cy.get(choiceinputAnchor).should("have.value", ""); + cy.get(choiceinputSubmitAnchor).should("be.visible"); + cy.get(choiceinputCorrectAnchor).should("not.exist"); + cy.get(choiceinputIncorrectAnchor).should("not.exist"); + cy.get(choiceinputPartialAnchor).should("not.exist"); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); + cy.log("Select correct answer"); + cy.get(choiceinputAnchor).select(`dog`); + cy.get(choiceinputSubmitAnchor).should("be.visible"); + cy.get(choiceinputCorrectAnchor).should("not.exist"); + cy.get(choiceinputIncorrectAnchor).should("not.exist"); + cy.get(choiceinputPartialAnchor).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.log("Click submit button"); + cy.get(choiceinputSubmitAnchor).click(); + cy.get(choiceinputSubmitAnchor).should("not.exist"); + cy.get(choiceinputCorrectAnchor).should("be.visible"); + cy.get(choiceinputIncorrectAnchor).should("not.exist"); + cy.get(choiceinputPartialAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); + cy.log("toggle inline"); + cy.get(cesc("#\\/inline")).click(); + cy.get(`${choiceinputAnchor} label:nth-of-type(3)`).should( + "be.visible", + ); + cy.get(choiceinputSubmitAnchor).should("not.exist"); + cy.get(choiceinputCorrectAnchor) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("correct"); + }); + cy.get(choiceinputIncorrectAnchor).should("not.exist"); + cy.get(choiceinputPartialAnchor).should("not.exist"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); + cy.log("Select partial credit answer"); + cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); + cy.get(choiceinputSubmitAnchor) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("check work"); + }); + cy.get(choiceinputCorrectAnchor).should("not.exist"); + cy.get(choiceinputIncorrectAnchor).should("not.exist"); + cy.get(choiceinputPartialAnchor).should("not.exist"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.log("Click submit button"); + cy.get(choiceinputSubmitAnchor).click(); + cy.get(choiceinputSubmitAnchor).should("not.exist"); + cy.get(choiceinputCorrectAnchor).should("not.exist"); + cy.get(choiceinputIncorrectAnchor).should("not.exist"); + cy.get(choiceinputPartialAnchor) + .invoke("text") + .then((text) => { + expect(text.trim().toLowerCase()).equal("50% correct"); + }); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); + cy.log("toggle inline"); + cy.get(cesc("#\\/inline")).click(); + cy.get(`${choiceinputAnchor} option:nth-of-type(3)`).should( + "be.visible", + ); + cy.get(choiceinputSubmitAnchor).should("not.exist"); + cy.get(choiceinputCorrectAnchor).should("not.exist"); + cy.get(choiceinputIncorrectAnchor).should("not.exist"); + cy.get(choiceinputPartialAnchor).should("have.text", "50 %"); }); }); - it("answer sugar from macro, text, and string, does not ignore blank string", () => { + it("immediate value used for submit button", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - hello -

$h there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - `, + a +

Enter value larger than 3:

+ + + $val > 3 + + +

Current response:

+

Submitted response:

+

Credit: $a.creditAchieved{assignNames="ca"}

+ `, }, "*", ); @@ -3327,526 +1454,285 @@ describe("Answer Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); + let submitAnchor = cesc2("#/a_submit"); + let correctAnchor = cesc2("#/a_correct"); + let incorrectAnchor = cesc2("#/a_incorrect"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); + cy.get(submitAnchor).should("be.visible"); + cy.get(correctAnchor).should("not.exist"); + cy.get(incorrectAnchor).should("not.exist"); - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("οΌΏ"); }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("οΌΏ"); }); + cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); + cy.get(cesc("#\\/val") + " textarea").type("3{enter}", { force: true }); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.get(submitAnchor).should("be.visible"); + cy.get(correctAnchor).should("not.exist"); + cy.get(incorrectAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); + cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("contain.text", "3"); - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); }); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("οΌΏ"); + }); + cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.get(cesc("#\\/a_submit")).click(); + + cy.get(submitAnchor).should("not.exist"); + cy.get(correctAnchor).should("not.exist"); + cy.get(incorrectAnchor).should("be.visible"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); + }); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); }); + cy.get(cesc(`#\\/ca`)).should("have.text", "0"); + + cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}4", { + force: true, }); - }); - // test for bug where submitted response was not initially text - // when had only one copy of referring to all submitted responses - it("answer sugar from one string, set to text, copy all responses", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Submitted responses:

-

To check how long to wait: $bi.value{name="b"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); + cy.get(submitAnchor).should("be.visible"); + cy.get(correctAnchor).should("not.exist"); + cy.get(incorrectAnchor).should("not.exist"); - cy.get(cesc("#\\/_p2")).should( - "have.text", - "Submitted responses: ", - ); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); + }); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); + }); + cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there {enter}`); + cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}3", { + force: true, + }); - cy.get(cesc("#\\/_p2")).should( - "have.text", - "Submitted responses: hello there ", - ); + cy.get(submitAnchor).should("be.visible"); + cy.get(correctAnchor).should("not.exist"); + cy.get(incorrectAnchor).should("not.exist"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log( - "click boolean input to know when core has finished processing", - ); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); }); + cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); + cy.get(cesc("#\\/a_submit")).click(); + cy.get(submitAnchor).should("not.exist"); + cy.get(correctAnchor).should("not.exist"); + cy.get(incorrectAnchor).should("be.visible"); - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log( - "click boolean input to know when core has finished processing", - ); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); }); + cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); + cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}5", { + force: true, }); - }); - it("answer sugar from one string, set to boolean", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

true

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response: $_answer1.submittedResponse{name="sr1"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

+ cy.get(submitAnchor).should("be.visible"); + cy.get(correctAnchor).should("not.exist"); + cy.get(incorrectAnchor).should("not.exist"); - `, - }, - "*", - ); - }); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); + }); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); + }); + cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc("#\\/val") + " textarea").blur(); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let booleaninputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let booleaninputAnchor = cesc2("#" + booleaninputName); - let booleaninputSubmitAnchor = cesc2( - "#" + booleaninputName + "_submit", - ); + cy.get(submitAnchor).should("be.visible"); + cy.get(correctAnchor).should("not.exist"); + cy.get(incorrectAnchor).should("not.exist"); - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); + cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "5"); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("5"); }); - - cy.log("Select correct answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("3"); }); + cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - cy.log("Press enter on submit button to submit"); - cy.get(booleaninputSubmitAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); + cy.get(cesc("#\\/a_submit")).click(); + cy.get(submitAnchor).should("not.exist"); + cy.get(correctAnchor).should("be.visible"); + cy.get(incorrectAnchor).should("not.exist"); - cy.log("Select wrong answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); + cy.get(cesc(`#\\/cr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("5"); }); - - cy.log("Submit answer"); - cy.get(booleaninputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([false]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); + cy.get(cesc(`#\\/sr`)) + .find(".mjx-mrow") + .eq(0) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("5"); }); - }); + cy.get(cesc(`#\\/ca`)).should("have.text", "1"); }); - it("answer sugar from one boolean", () => { + it("maximum number of attempts", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

true

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response: $_answer1.submittedResponse{name="sr1"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

+

x

+

x

+

x

+

x

+ +

hello

+

hello

+

hello

+

hello

+ +

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

+ +

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

- `, +

true

+

true

+

true

+

true

+ `, }, "*", ); @@ -3856,721 +1742,382 @@ describe("Answer Tag Tests", function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let booleaninputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let booleaninputAnchor = cesc2("#" + booleaninputName); - let booleaninputSubmitAnchor = cesc2( - "#" + booleaninputName + "_submit", + + let inputNames = [...Array(20).keys()].map( + (n) => + stateVariables[`/_answer${n + 1}`].stateValues + .inputChildren[0].componentName, ); - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); + cy.log("Submit correct answers"); + cy.get(cesc2("#" + inputNames[0]) + " textarea").type("x{enter}", { + force: true, }); - - cy.log("Select correct answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); + cy.get(cesc2("#" + inputNames[1]) + " textarea").type("x{enter}", { + force: true, }); - - cy.log("Press enter on submit button to submit"); - cy.get(booleaninputSubmitAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); + cy.get(cesc2("#" + inputNames[2]) + " textarea").type("x{enter}", { + force: true, }); - - cy.log("Select wrong answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); + cy.get(cesc2("#" + inputNames[3]) + " textarea").type("x{enter}", { + force: true, }); + cy.get(cesc2("#/_answer3_submit")).click(); + cy.get(cesc2("#/_answer4_submit")).click(); + cy.get(cesc2("#" + inputNames[0]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[1]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#/_answer3_correct")).should("be.visible"); + cy.get(cesc2("#/_answer4_correct")).should("be.visible"); - cy.log("Submit answer"); - cy.get(booleaninputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([false]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - }); - }); - - it("answer sugar from macro and string, set to boolean", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - false -

not $b

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response: $_answer1.submittedResponse{name="sr1"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - `, - }, - "*", + cy.get(cesc2("#" + inputNames[4]) + "_input").type("hello{enter}"); + cy.get(cesc2("#" + inputNames[5]) + "_input").type("hello{enter}"); + cy.get(cesc2("#" + inputNames[6]) + "_input").type("hello{enter}"); + cy.get(cesc2("#" + inputNames[7]) + "_input").type("hello{enter}"); + cy.get(cesc2("#/_answer7_submit")).click(); + cy.get(cesc2("#/_answer8_submit")).click(); + cy.get(cesc2("#" + inputNames[4]) + "_correct").should( + "be.visible", ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let booleaninputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let booleaninputAnchor = cesc2("#" + booleaninputName); - let booleaninputSubmitAnchor = cesc2( - "#" + booleaninputName + "_submit", + cy.get(cesc2("#" + inputNames[5]) + "_correct").should( + "be.visible", ); + cy.get(cesc2("#/_answer7_correct")).should("be.visible"); + cy.get(cesc2("#/_answer8_correct")).should("be.visible"); - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Select correct answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Press enter on submit button to submit"); - cy.get(booleaninputSubmitAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Select wrong answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Submit answer"); - cy.get(booleaninputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([false]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - }); - }); + cy.get(cesc2("#/_choiceinput1")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput2")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput3")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput4")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput1_submit")).click(); + cy.get(cesc2("#/_choiceinput2_submit")).click(); + cy.get(cesc2("#/_answer11_submit")).click(); + cy.get(cesc2("#/_answer12_submit")).click(); + cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); + cy.get(cesc2("#/_choiceinput2_correct")).should("be.visible"); + cy.get(cesc2("#/_answer11_correct")).should("be.visible"); + cy.get(cesc2("#/_answer12_correct")).should("be.visible"); - it("answer sugar from boolean and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

not false

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response: $_answer1.submittedResponse{name="sr1"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

+ cy.get(cesc("#\\/_choiceinput5")).select(`yes`); + cy.get(cesc("#\\/_choiceinput6")).select(`yes`); + cy.get(cesc("#\\/_choiceinput7")).select(`yes`); + cy.get(cesc("#\\/_choiceinput8")).select(`yes`); + cy.get(cesc2("#/_choiceinput5_submit")).click(); + cy.get(cesc2("#/_choiceinput6_submit")).click(); + cy.get(cesc2("#/_answer15_submit")).click(); + cy.get(cesc2("#/_answer16_submit")).click(); + cy.get(cesc2("#/_choiceinput5_correct")).should("be.visible"); + cy.get(cesc2("#/_choiceinput6_correct")).should("be.visible"); + cy.get(cesc2("#/_answer15_correct")).should("be.visible"); + cy.get(cesc2("#/_answer16_correct")).should("be.visible"); - `, - }, - "*", + cy.get(cesc2("#" + inputNames[16])).click(); + cy.get(cesc2("#" + inputNames[17])).click(); + cy.get(cesc2("#" + inputNames[18])).click(); + cy.get(cesc2("#" + inputNames[19])).click(); + cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); + cy.get(cesc2("#" + inputNames[17]) + "_submit").click(); + cy.get(cesc2("#/_answer19_submit")).click(); + cy.get(cesc2("#/_answer20_submit")).click(); + cy.get(cesc2("#" + inputNames[16]) + "_correct").should( + "be.visible", ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let booleaninputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let booleaninputAnchor = cesc2("#" + booleaninputName); - let booleaninputSubmitAnchor = cesc2( - "#" + booleaninputName + "_submit", + cy.get(cesc2("#" + inputNames[17]) + "_correct").should( + "be.visible", ); + cy.get(cesc2("#/_answer19_correct")).should("be.visible"); + cy.get(cesc2("#/_answer20_correct")).should("be.visible"); - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Select correct answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Press enter on submit button to submit"); - cy.get(booleaninputSubmitAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Select wrong answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Submit answer"); - cy.get(booleaninputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([false]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - }); - }); - - it("warning for sugar with invalid type", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x

-

Credit for submitted response: $_answer1.creditAchieved

- `, - }, - "*", + cy.log("Submit incorrect answers"); + cy.get(cesc2("#" + inputNames[0]) + " textarea").type( + "{end}{backspace}y", + { force: true }, ); - }); + cy.get(cesc2("#" + inputNames[1]) + " textarea").type( + "{end}{backspace}y", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[2]) + " textarea").type( + "{end}{backspace}y", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[3]) + " textarea").type( + "{end}{backspace}y", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[0]) + "_submit").click(); + cy.get(cesc2("#" + inputNames[1]) + "_submit").click(); + cy.get(cesc2("#/_answer3_submit")).click(); + cy.get(cesc2("#/_answer4_submit")).click(); + cy.get(cesc2("#" + inputNames[0]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[1]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#/_answer3_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer4_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#" + inputNames[4]) + "_input") + .clear() + .type("bye"); + cy.get(cesc2("#" + inputNames[5]) + "_input") + .clear() + .type("bye"); + cy.get(cesc2("#" + inputNames[6]) + "_input") + .clear() + .type("bye"); + cy.get(cesc2("#" + inputNames[7]) + "_input") + .clear() + .type("bye"); + cy.get(cesc2("#" + inputNames[4]) + "_submit").click(); + cy.get(cesc2("#" + inputNames[5]) + "_submit").click(); + cy.get(cesc2("#/_answer7_submit")).click(); + cy.get(cesc2("#/_answer8_submit")).click(); + cy.get(cesc2("#" + inputNames[4]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[5]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#/_answer7_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer8_incorrect")).should("be.visible"); - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); + cy.get(cesc2("#/_choiceinput1")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput2")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput3")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput4")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput1_submit")).click(); + cy.get(cesc2("#/_choiceinput2_submit")).click(); + cy.get(cesc2("#/_answer11_submit")).click(); + cy.get(cesc2("#/_answer12_submit")).click(); + cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); + cy.get(cesc2("#/_choiceinput2_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer11_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer12_incorrect")).should("be.visible"); - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(1); + cy.get(cesc("#\\/_choiceinput5")).select(`no`); + cy.get(cesc("#\\/_choiceinput6")).select(`no`); + cy.get(cesc("#\\/_choiceinput7")).select(`no`); + cy.get(cesc("#\\/_choiceinput8")).select(`no`); + cy.get(cesc2("#/_choiceinput5_submit")).click(); + cy.get(cesc2("#/_choiceinput6_submit")).click(); + cy.get(cesc2("#/_answer15_submit")).click(); + cy.get(cesc2("#/_answer16_submit")).click(); + cy.get(cesc2("#/_choiceinput5_incorrect")).should("be.visible"); + cy.get(cesc2("#/_choiceinput6_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer15_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer16_incorrect")).should("be.visible"); - expect(errorWarnings.warnings[0].message).contain( - "Invalid type for answer: bad", + cy.get(cesc2("#" + inputNames[16])).click(); + cy.get(cesc2("#" + inputNames[17])).click(); + cy.get(cesc2("#" + inputNames[18])).click(); + cy.get(cesc2("#" + inputNames[19])).click(); + cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); + cy.get(cesc2("#" + inputNames[17]) + "_submit").click(); + cy.get(cesc2("#/_answer19_submit")).click(); + cy.get(cesc2("#/_answer20_submit")).click(); + cy.get(cesc2("#" + inputNames[16]) + "_incorrect").should( + "be.visible", ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(3); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(6); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(3); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(34); - }); - - cy.get(cesc2("#/_answer1") + " textarea").type("x{enter}", { - force: true, - }); - cy.get(cesc2("#/_p2")).should( - "have.text", - "Credit for submitted response: 1", - ); - }); - - it("answer award with math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", + cy.get(cesc2("#" + inputNames[17]) + "_incorrect").should( + "be.visible", ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/_answer19_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer20_incorrect")).should("be.visible"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + cy.log("Type to submit correct answers again"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + // the 2nd and 4th input should be disabled, + // but this isn't working yet. + // For now, best we can do is make sure button still say incorrect + cy.get(cesc2("#" + inputNames[0]) + " textarea").type( + "{end}{backspace}x", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[1]) + " textarea").type( + "{end}{backspace}x", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[2]) + " textarea").type( + "{end}{backspace}x", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[3]) + " textarea").type( + "{end}{backspace}x", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[0]) + "_submit").click(); + cy.get(cesc2("#/_answer3_submit")).click(); + cy.get(cesc2("#" + inputNames[0]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[1]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#/_answer3_correct")).should("be.visible"); + cy.get(cesc2("#/_answer4_incorrect")).should("be.visible"); - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); + cy.get(cesc2("#" + inputNames[4]) + "_input") + .clear() + .type("hello"); + cy.get(cesc2("#" + inputNames[5]) + "_input").should("be.disabled"); + cy.get(cesc2("#" + inputNames[6]) + "_input") + .clear() + .type("hello"); + cy.get(cesc2("#" + inputNames[7]) + "_input").should("be.disabled"); + cy.get(cesc2("#" + inputNames[4]) + "_submit").click(); + cy.get(cesc2("#/_answer7_submit")).click(); + cy.get(cesc2("#" + inputNames[4]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[5]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#/_answer7_correct")).should("be.visible"); + cy.get(cesc2("#/_answer8_incorrect")).should("be.visible"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.get(cesc2("#/_choiceinput1")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput2")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput3")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput4")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput1_submit")).click(); + cy.get(cesc2("#/_answer11_submit")).click(); + cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); + cy.get(cesc2("#/_choiceinput2_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer11_correct")).should("be.visible"); + cy.get(cesc2("#/_answer12_incorrect")).should("be.visible"); - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); + cy.get(cesc("#\\/_choiceinput5")).select(`yes`); + cy.get(cesc("#\\/_choiceinput6")).should("be.disabled"); + cy.get(cesc("#\\/_choiceinput7")).select(`yes`); + cy.get(cesc("#\\/_choiceinput8")).should("be.disabled"); + cy.get(cesc2("#/_choiceinput5_submit")).click(); + cy.get(cesc2("#/_answer15_submit")).click(); + cy.get(cesc2("#/_choiceinput5_correct")).should("be.visible"); + cy.get(cesc2("#/_choiceinput6_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer15_correct")).should("be.visible"); + cy.get(cesc2("#/_answer16_incorrect")).should("be.visible"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); + cy.get(cesc2("#" + inputNames[16])).click(); + cy.get(cesc2("#" + inputNames[17]) + "_input").should( + "be.disabled", + ); + cy.get(cesc2("#" + inputNames[18])).click(); + cy.get(cesc2("#" + inputNames[19]) + "_input").should( + "be.disabled", + ); + cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); + cy.get(cesc2("#/_answer19_submit")).click(); + cy.get(cesc2("#" + inputNames[16]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[17]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#/_answer19_correct")).should("be.visible"); + cy.get(cesc2("#/_answer20_incorrect")).should("be.visible"); }); }); - it("answer award with sugared string", () => { + it("disable after correct", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

x+y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, +

x

+

x

+

x

+

x

+ +

hello

+

hello

+

hello

+

hello

+ +

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

+ +

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

+ +

true

+

true

+

true

+

true

+ `, }, "*", ); @@ -4580,27389 +2127,366 @@ describe("Answer Tag Tests", function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); + let inputNames = [...Array(20).keys()].map( + (n) => + stateVariables[`/_answer${n + 1}`].stateValues + .inputChildren[0].componentName, + ); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); + cy.log("Submit incorrect answers"); + cy.get(cesc2("#" + inputNames[0]) + " textarea").type("y{enter}", { + force: true, }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); + cy.get(cesc2("#" + inputNames[1]) + " textarea").type("y{enter}", { + force: true, }); - - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); + cy.get(cesc2("#" + inputNames[2]) + " textarea").type("y{enter}", { + force: true, }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); + cy.get(cesc2("#" + inputNames[3]) + " textarea").type("y{enter}", { + force: true, }); - }); - }); - - it("answer award with sugared macro", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x+y -

$xy

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", + cy.get(cesc2("#/_answer3_submit")).click(); + cy.get(cesc2("#/_answer4_submit")).click(); + cy.get(cesc2("#" + inputNames[0]) + "_incorrect").should( + "be.visible", ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#" + inputNames[1]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#/_answer3_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer4_incorrect")).should("be.visible"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + cy.get(cesc2("#" + inputNames[4]) + "_input").type("bye{enter}"); + cy.get(cesc2("#" + inputNames[5]) + "_input").type("bye{enter}"); + cy.get(cesc2("#" + inputNames[6]) + "_input").type("bye{enter}"); + cy.get(cesc2("#" + inputNames[7]) + "_input").type("bye{enter}"); + cy.get(cesc2("#/_answer7_submit")).click(); + cy.get(cesc2("#/_answer8_submit")).click(); + cy.get(cesc2("#" + inputNames[4]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[5]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#/_answer7_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer8_incorrect")).should("be.visible"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.get(cesc2("#/_choiceinput1")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput2")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput3")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput4")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput1_submit")).click(); + cy.get(cesc2("#/_choiceinput2_submit")).click(); + cy.get(cesc2("#/_answer11_submit")).click(); + cy.get(cesc2("#/_answer12_submit")).click(); + cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); + cy.get(cesc2("#/_choiceinput2_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer11_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer12_incorrect")).should("be.visible"); - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); + cy.get(cesc("#\\/_choiceinput5")).select(`no`); + cy.get(cesc("#\\/_choiceinput6")).select(`no`); + cy.get(cesc("#\\/_choiceinput7")).select(`no`); + cy.get(cesc("#\\/_choiceinput8")).select(`no`); + cy.get(cesc2("#/_choiceinput5_submit")).click(); + cy.get(cesc2("#/_choiceinput6_submit")).click(); + cy.get(cesc2("#/_answer15_submit")).click(); + cy.get(cesc2("#/_answer16_submit")).click(); + cy.get(cesc2("#/_choiceinput5_incorrect")).should("be.visible"); + cy.get(cesc2("#/_choiceinput6_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer15_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer16_incorrect")).should("be.visible"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); + cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); + cy.get(cesc2("#" + inputNames[17]) + "_submit").click(); + cy.get(cesc2("#/_answer19_submit")).click(); + cy.get(cesc2("#/_answer20_submit")).click(); + cy.get(cesc2("#" + inputNames[16]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[17]) + "_incorrect").should( + "be.visible", + ); + cy.get(cesc2("#/_answer19_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer20_incorrect")).should("be.visible"); - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); + cy.log("Submit correct answers"); + cy.get(cesc2("#" + inputNames[0]) + " textarea").type( + "{end}{backspace}x", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[1]) + " textarea").type( + "{end}{backspace}x", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[2]) + " textarea").type( + "{end}{backspace}x", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[3]) + " textarea").type( + "{end}{backspace}x", + { force: true }, + ); + cy.get(cesc2("#" + inputNames[0]) + "_submit").click(); + cy.get(cesc2("#" + inputNames[1]) + "_submit").click(); + cy.get(cesc2("#/_answer3_submit")).click(); + cy.get(cesc2("#/_answer4_submit")).click(); + cy.get(cesc2("#" + inputNames[0]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[1]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#/_answer3_correct")).should("be.visible"); + cy.get(cesc2("#/_answer4_correct")).should("be.visible"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.get(cesc2("#" + inputNames[4]) + "_input") + .clear() + .type("hello"); + cy.get(cesc2("#" + inputNames[5]) + "_input") + .clear() + .type("hello"); + cy.get(cesc2("#" + inputNames[6]) + "_input") + .clear() + .type("hello"); + cy.get(cesc2("#" + inputNames[7]) + "_input") + .clear() + .type("hello"); + cy.get(cesc2("#" + inputNames[4]) + "_submit").click(); + cy.get(cesc2("#" + inputNames[5]) + "_submit").click(); + cy.get(cesc2("#/_answer7_submit")).click(); + cy.get(cesc2("#/_answer8_submit")).click(); + cy.get(cesc2("#" + inputNames[4]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[5]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#/_answer7_correct")).should("be.visible"); + cy.get(cesc2("#/_answer8_correct")).should("be.visible"); - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); + cy.get(cesc2("#/_choiceinput1")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput2")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput3")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput4")) + .contains("yes") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput1_submit")).click(); + cy.get(cesc2("#/_choiceinput2_submit")).click(); + cy.get(cesc2("#/_answer11_submit")).click(); + cy.get(cesc2("#/_answer12_submit")).click(); + cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); + cy.get(cesc2("#/_choiceinput2_correct")).should("be.visible"); + cy.get(cesc2("#/_answer11_correct")).should("be.visible"); + cy.get(cesc2("#/_answer12_correct")).should("be.visible"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); + cy.get(cesc("#\\/_choiceinput5")).select(`yes`); + cy.get(cesc("#\\/_choiceinput6")).select(`yes`); + cy.get(cesc("#\\/_choiceinput7")).select(`yes`); + cy.get(cesc("#\\/_choiceinput8")).select(`yes`); + cy.get(cesc2("#/_choiceinput5_submit")).click(); + cy.get(cesc2("#/_choiceinput6_submit")).click(); + cy.get(cesc2("#/_answer15_submit")).click(); + cy.get(cesc2("#/_answer16_submit")).click(); + cy.get(cesc2("#/_choiceinput5_correct")).should("be.visible"); + cy.get(cesc2("#/_choiceinput6_correct")).should("be.visible"); + cy.get(cesc2("#/_answer15_correct")).should("be.visible"); + cy.get(cesc2("#/_answer16_correct")).should("be.visible"); - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); + cy.get(cesc2("#" + inputNames[16])).click(); + cy.get(cesc2("#" + inputNames[17])).click(); + cy.get(cesc2("#" + inputNames[18])).click(); + cy.get(cesc2("#" + inputNames[19])).click(); + cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); + cy.get(cesc2("#" + inputNames[17]) + "_submit").click(); + cy.get(cesc2("#/_answer19_submit")).click(); + cy.get(cesc2("#/_answer20_submit")).click(); + cy.get(cesc2("#" + inputNames[16]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#" + inputNames[17]) + "_correct").should( + "be.visible", + ); + cy.get(cesc2("#/_answer19_correct")).should("be.visible"); + cy.get(cesc2("#/_answer20_correct")).should("be.visible"); - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - }); - }); + cy.log("Type to submit incorrect answers again"); - it("answer award with sugared macros and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - xy -

$x+$y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - }); - }); - - it("answer award with sugared macro, text, and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x -

$x+y

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - }); - }); - - it("answer with copied award, createComponentOfType specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x$x+y -

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - }); - }); - - it("answer award with math, initally unresolved", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+y-3+$n

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - $n3{name="n2"} - $num1{name="n"} - $n2+$num2 - $n3+$num3 - $num3{name="n3"} - 1 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter wrong answer"); - cy.get(mathinputAnchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - }); - }); - - it("answer sugar from mathList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+y z

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y, z`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y,z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y,z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", ["+", "x", "y"], "z"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - ["+", "x", "y"], - "z", - ]); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y,z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y,z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y,z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", ["+", "x", "y"], "z"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", ["+", "x", "y"], "z"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - ["+", "x", "y"], - "z", - ]); - }); - - cy.log("Enter partially correct answer"); - cy.get(mathinputAnchor) - .type( - `{end}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}`, - { - force: true, - }, - ) - .blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x,z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x,z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y,z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", "x", "z"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", ["+", "x", "y"], "z"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - "x", - "z", - ]); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x,z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x,z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x,z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", "x", "z"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", "x", "z"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - "x", - "z", - ]); - }); - - cy.log("Submit incorrect answer"); - cy.get(mathinputAnchor).type( - `{end}{backspace}{backspace}{backspace}`, - { - force: true, - delay: 100, - }, - ); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - }); - - cy.log("Submit other partially correct answer"); - cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}z`, { - force: true, - delay: 100, - }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["z"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["z"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "z", - ); - }); - }); - }); - - it("answer award with mathList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+y z

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y, z`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y,z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y,z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", ["+", "x", "y"], "z"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - ["+", "x", "y"], - "z", - ]); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y,z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y,z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y,z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", ["+", "x", "y"], "z"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", ["+", "x", "y"], "z"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - ["+", "x", "y"], - "z", - ]); - }); - - cy.log("Enter partially correct answer"); - cy.get(mathinputAnchor) - .type( - `{end}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}`, - { - force: true, - }, - ) - .blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x,z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x,z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y,z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", "x", "z"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", ["+", "x", "y"], "z"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - "x", - "z", - ]); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x,z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x,z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x,z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", "x", "z"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", "x", "z"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - "x", - "z", - ]); - }); - - cy.log("Submit incorrect answer"); - cy.get(mathinputAnchor).type( - `{end}{backspace}{backspace}{backspace}`, - { - force: true, - delay: 100, - }, - ); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - }); - - cy.log("Submit other partially correct answer"); - cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}z`, { - force: true, - delay: 100, - }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["z"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["z"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "z", - ); - }); - }); - }); - - it("answer from mathList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - $mi1 $mi2 = x+y z -

-

Current response: $_answer1.currentResponses{assignNames="cr1 cr2"}

-

Submitted response: $_answer1.submittedResponses{assignNames="sr1 sr2" createComponentOfType="math" numComponents="2"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let mathinput1Name = "/mi1"; - let mathinput1Anchor = cesc2("#" + mathinput1Name) + " textarea"; - let mathinput2Name = "/mi2"; - let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - let submitAnchor = cesc2("#/_answer1_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F", "\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinput1Name].stateValues.value).eq( - "\uFF3F", - ); - expect(stateVariables[mathinput2Name].stateValues.value).eq( - "\uFF3F", - ); - }); - - cy.log("Type correct answer in"); - cy.get(mathinput1Anchor).type(`x+y`, { force: true }).blur(); - cy.get(mathinput2Anchor).type(`z`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"], "z"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinput1Name].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables[mathinput2Name].stateValues.value).eqls("z"); - }); - - cy.log("Press enter to submit"); - cy.get(submitAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"], "z"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"], "z"]); - expect(stateVariables[mathinput1Name].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables[mathinput2Name].stateValues.value).eqls("z"); - }); - - cy.log("Enter partially correct answer"); - cy.get(mathinput1Anchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", "z"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"], "z"]); - expect(stateVariables[mathinput1Name].stateValues.value).eqls("x"); - expect(stateVariables[mathinput2Name].stateValues.value).eqls("z"); - }); - - cy.log("Submit answer"); - cy.get(submitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", "z"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x", "z"]); - expect(stateVariables[mathinput1Name].stateValues.value).eqls("x"); - expect(stateVariables[mathinput2Name].stateValues.value).eqls("z"); - }); - - cy.log("Submit incorrect answer"); - cy.get(mathinput2Anchor).type( - `{end}{backspace}{backspace}{backspace}`, - { - force: true, - delay: 100, - }, - ); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(submitAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", "\uff3f"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x", "\uff3f"]); - expect(stateVariables[mathinput1Name].stateValues.value).eqls("x"); - expect(stateVariables[mathinput2Name].stateValues.value).eqls( - "\uff3f", - ); - }); - - cy.log("Submit other partially correct answer"); - cy.get(mathinput1Anchor).type(`{end}{backspace}{backspace}z`, { - force: true, - delay: 100, - }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(submitAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "z"); - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["z", "\uff3f"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["z", "\uff3f"]); - expect(stateVariables[mathinput1Name].stateValues.value).eqls("z"); - expect(stateVariables[mathinput2Name].stateValues.value).eqls( - "\uff3f", - ); - }); - }); - - it("answer sugar from numberList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

1 2

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`1, 2`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "1,2"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", 1, 2]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - 1, - 2, - ]); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "1,2"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", 1, 2]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", 1, 2]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - 1, - 2, - ]); - }); - - cy.log("Enter partially correct answer"); - cy.get(mathinputAnchor).type(`{home}3`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "31,2"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31,2"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", 31, 2]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", 1, 2]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - 31, - 2, - ]); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "31,2"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31,2"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31,2"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", 31, 2]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", 31, 2]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - 31, - 2, - ]); - }); - - cy.log("Submit incorrect answer"); - cy.get(mathinputAnchor).type( - `{end}{backspace}{backspace}{backspace}{backspace}`, - { force: true, delay: 100 }, - ); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "31"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "31"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([31]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([31]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - 31, - ); - }); - - cy.log("Submit other partially correct answer"); - cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}1`, { - force: true, - delay: 100, - }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "1"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "1"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([1]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([1]); - expect(stateVariables[mathinputName].stateValues.value).eqls(1); - }); - }); - }); - - it("answer award with numberList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

1 2

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`1, 2`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "1,2"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", 1, 2]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - 1, - 2, - ]); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "1,2"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", 1, 2]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", 1, 2]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - 1, - 2, - ]); - }); - - cy.log("Enter partially correct answer"); - cy.get(mathinputAnchor).type(`{home}3`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "31,2"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31,2"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", 31, 2]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", 1, 2]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - 31, - 2, - ]); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "31,2"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31,2"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31,2"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["list", 31, 2]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["list", 31, 2]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "list", - 31, - 2, - ]); - }); - - cy.log("Submit incorrect answer"); - cy.get(mathinputAnchor).type( - `{end}{backspace}{backspace}{backspace}{backspace}`, - { force: true, delay: 100 }, - ); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "31"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "31"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([31]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([31]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - 31, - ); - }); - - cy.log("Submit other partially correct answer"); - cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}1`, { - force: true, - delay: 100, - }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "1"); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "1"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([1]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([1]); - expect(stateVariables[mathinputName].stateValues.value).eqls(1); - }); - }); - }); - - it("answer award with text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - }); - }); - - it("answer set to text, award with text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - }); - }); - - it("answer set to text, award with sugared string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - }); - }); - - it("answer set to text, award with sugared macro and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - hello -

$h there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - }); - }); - - it("answer award with text and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - }); - }); - - it("answer award with text, macro, and string, does not ignore blank string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - hello -

$h there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - }); - }); - - it("answer award with text, initally unresolved", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

$n

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - $n3{name="n2"} - $text1{name="n"} - $n2 $text2 - $n4 - $text3{name="n3"} - hello - $text4{name="n4"} - there - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter wrong answer"); - cy.get(textinputAnchor).clear().type(`hellothere`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hellothere"); - cy.get(cesc("#\\/cr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hellothere"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hellothere", - ); - }); - - cy.log("Enter another correct answer"); - cy.get(textinputAnchor).clear().type(`hello there`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hellothere"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hellothere"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - }); - }); - - it("answer sugar from textlist", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello , there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello , there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello , there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello , there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello , there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello , there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello , there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello , there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello , there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello , there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello , there ", - ); - }); - - cy.log("Enter partially correct answer"); - cy.get(textinputAnchor).clear().type(`hello,then`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello,then"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello,then"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello , there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello,then"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello , there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello,then", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello,then"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello,then"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello,then"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello,then"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello,then"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello,then", - ); - }); - - cy.log("Submit incorrect answer"); - cy.get(textinputAnchor).clear().type(`hello there`, { delay: 100 }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit other partially correct answer"); - cy.get(textinputAnchor).clear().type(`there`, { delay: 100 }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "there"); - cy.get(cesc("#\\/cr1")).should("have.text", "there"); - cy.get(cesc("#\\/sr1")).should("have.text", "there"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "there", - ); - }); - }); - }); - - it("answer award with textlist", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello there

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello , there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello , there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello , there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello , there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello , there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello , there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello , there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello , there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello , there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello , there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello , there ", - ); - }); - - cy.log("Enter partially correct answer"); - cy.get(textinputAnchor).clear().type(`hello,then`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello,then"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello,then"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello , there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello,then"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello , there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello,then", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello,then"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello,then"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello,then"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello,then"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello,then"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello,then", - ); - }); - - cy.log("Submit incorrect answer"); - cy.get(textinputAnchor).clear().type(`hello there`, { delay: 100 }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("Submit other partially correct answer"); - cy.get(textinputAnchor).clear().type(`there`, { delay: 100 }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "there"); - cy.get(cesc("#\\/cr1")).should("have.text", "there"); - cy.get(cesc("#\\/sr1")).should("have.text", "there"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["there"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["there"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "there", - ); - }); - }); - }); - - it("answer from textlist", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - $ti1 $ti2= hello there -

-

Current responses: $_answer1.currentResponses{assignNames="cr1 cr2"}

-

Submitted responses: $_answer1.submittedResponses{assignNames="sr1 sr2"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let textinput1Name = "/ti1"; - let textinput1Anchor = cesc2("#" + textinput1Name + "_input"); - let textinput2Name = "/ti2"; - let textinput2Anchor = cesc2("#" + textinput2Name + "_input"); - let submitAnchor = cesc2("#/_answer1_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinput1Anchor).should("have.value", ""); - cy.get(textinput2Anchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/cr2")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("not.exist"); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["", ""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinput1Name].stateValues.value).eq(""); - expect(stateVariables[textinput2Name].stateValues.value).eq(""); - }); - - cy.log("Type correct answers in"); - cy.get(textinput1Anchor).type(` hello `).blur(); - cy.get(textinput2Anchor).type(` there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinput1Anchor).should("have.value", " hello "); - cy.get(textinput2Anchor).should("have.value", " there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello "); - cy.get(cesc("#\\/cr2")).should("have.text", " there "); - cy.get(cesc("#\\/sr1")).should("not.exist"); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello ", " there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinput1Name].stateValues.value).eq( - " hello ", - ); - expect(stateVariables[textinput2Name].stateValues.value).eq( - " there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(submitAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinput1Anchor).should("have.value", " hello "); - cy.get(textinput2Anchor).should("have.value", " there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello "); - cy.get(cesc("#\\/cr2")).should("have.text", " there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello "); - cy.get(cesc("#\\/sr2")).should("have.text", " there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello ", " there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello ", " there "]); - expect(stateVariables[textinput1Name].stateValues.value).eq( - " hello ", - ); - expect(stateVariables[textinput2Name].stateValues.value).eq( - " there ", - ); - }); - - cy.log("Enter partially correct answer"); - cy.get(textinput1Anchor).clear().type(`hello`).blur(); - cy.get(textinput2Anchor).clear().type(`then`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinput1Anchor).should("have.value", "hello"); - cy.get(textinput2Anchor).should("have.value", "then"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello"); - cy.get(cesc("#\\/cr2")).should("have.text", "then"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello "); - cy.get(cesc("#\\/sr2")).should("have.text", " there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello", "then"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello ", " there "]); - expect(stateVariables[textinput1Name].stateValues.value).eq( - "hello", - ); - expect(stateVariables[textinput2Name].stateValues.value).eq("then"); - }); - - cy.log("Submit answer"); - cy.get(submitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinput1Anchor).should("have.value", "hello"); - cy.get(textinput2Anchor).should("have.value", "then"); - cy.get(cesc("#\\/cr1")).should("have.text", "hello"); - cy.get(cesc("#\\/cr2")).should("have.text", "then"); - cy.get(cesc("#\\/sr1")).should("have.text", "hello"); - cy.get(cesc("#\\/sr2")).should("have.text", "then"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello", "then"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello", "then"]); - expect(stateVariables[textinput1Name].stateValues.value).eq( - "hello", - ); - expect(stateVariables[textinput2Name].stateValues.value).eq("then"); - }); - - cy.log("Submit incorrect answer"); - cy.get(textinput2Anchor).clear(); - cy.get(textinput1Anchor).clear().type(`hello, there`, { delay: 100 }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(submitAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinput1Anchor).should("have.value", "hello, there"); - cy.get(textinput2Anchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", "hello, there"); - cy.get(cesc("#\\/cr2")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", "hello, there"); - cy.get(cesc("#\\/sr2")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["hello, there", ""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["hello, there", ""]); - expect(stateVariables[textinput1Name].stateValues.value).eq( - "hello, there", - ); - expect(stateVariables[textinput2Name].stateValues.value).eq(""); - }); - - cy.log("Submit other partially correct answer"); - cy.get(textinput1Anchor).clear().type(`there`, { delay: 100 }); - // Note: have to wait for core to respond to at least first keystroke - // or the renderer will not be set to allow a submission - // (delayed typing to make sure can test case where submit before core has responded to all, - // in case where have core set for a delayed response) - cy.get(submitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinput1Anchor).should("have.value", "there"); - cy.get(textinput2Anchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", "there"); - cy.get(cesc("#\\/cr2")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", "there"); - cy.get(cesc("#\\/sr2")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["there", ""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["there", ""]); - expect(stateVariables[textinput1Name].stateValues.value).eq( - "there", - ); - expect(stateVariables[textinput2Name].stateValues.value).eq(""); - }); - }); - - it("answer award with boolean", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

true

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response: $_answer1.submittedResponse{name="sr1"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let booleaninputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let booleaninputAnchor = cesc2("#" + booleaninputName); - let booleaninputSubmitAnchor = cesc2( - "#" + booleaninputName + "_submit", - ); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Select correct answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Press enter on submit button to submit"); - cy.get(booleaninputSubmitAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Select wrong answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Submit answer"); - cy.get(booleaninputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([false]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - }); - }); - - it("answer set to boolean, award with boolean", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

true

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response: $_answer1.submittedResponse{name="sr1"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let booleaninputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let booleaninputAnchor = cesc2("#" + booleaninputName); - let booleaninputSubmitAnchor = cesc2( - "#" + booleaninputName + "_submit", - ); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Select correct answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Press enter on submit button to submit"); - cy.get(booleaninputSubmitAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Select wrong answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Submit answer"); - cy.get(booleaninputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([false]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - }); - }); - - it("answer set to boolean, award with sugared macro and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - false -

not $b

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response: $_answer1.submittedResponse{name="sr1"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let booleaninputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let booleaninputAnchor = cesc2("#" + booleaninputName); - let booleaninputSubmitAnchor = cesc2( - "#" + booleaninputName + "_submit", - ); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Select correct answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Press enter on submit button to submit"); - cy.get(booleaninputSubmitAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Select wrong answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Submit answer"); - cy.get(booleaninputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([false]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - }); - }); - - it("answer award with sugared boolean and string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - false -

not false

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response: $_answer1.submittedResponse{name="sr1"}

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let booleaninputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let booleaninputAnchor = cesc2("#" + booleaninputName); - let booleaninputSubmitAnchor = cesc2( - "#" + booleaninputName + "_submit", - ); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Select correct answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Press enter on submit button to submit"); - cy.get(booleaninputSubmitAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "true"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([true]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - true, - ); - }); - - cy.log("Select wrong answer"); - cy.get(booleaninputAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "true"); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([true]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - - cy.log("Submit answer"); - cy.get(booleaninputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/cr1")).should("have.text", "false"); - cy.get(cesc("#\\/sr1")).should("have.text", "false"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([false]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([false]); - expect(stateVariables[booleaninputName].stateValues.value).eq( - false, - ); - }); - }); - }); - - it("answer multiple shortcut awards", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+yx

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter partially correct answer"); - cy.get(mathinputAnchor) - .type(`{end}{backspace}{backspace}`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - - cy.log("Enter incorrect answer"); - // cy.get(mathinputAnchor); - cy.get(mathinputAnchor) - .type(`{end}{backspace}y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "y", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - - cy.log("Submit answer"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["y"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "y", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('y'); - }); - }); - }); - - it("answer multiple shortcut awards, initially unresolved", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

$rightAnswerx-3+$n

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- - x+y-3+$n - $n3{name="n2"} - $num1{name="n"} - $n2+$num2 - $n3+$num3 - $num3{name="n3"} - 1 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter partially correct answer"); - cy.get(mathinputAnchor) - .type( - `{rightarrow}{rightarrow}{rightarrow}{backspace}{backspace}`, - { - force: true, - }, - ) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - - cy.log("Enter incorrect answer"); - cy.get(mathinputAnchor) - .type(`{rightarrow}{backspace}y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'y'); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "y", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - - cy.log("Submit answer"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'y'); - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "y"); - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["y"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "y", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('y'); - }); - }); - }); - - it("answer multiple text awards", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello therebye

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter partially correct answer"); - cy.get(textinputAnchor).clear().type(`bye`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(cesc("#\\/cr1")).should("have.text", "bye"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["bye"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "bye", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(cesc("#\\/cr1")).should("have.text", "bye"); - cy.get(cesc("#\\/sr1")).should("have.text", "bye"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["bye"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["bye"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "bye", - ); - }); - - cy.log("Enter incorrect answer"); - cy.get(textinputAnchor).clear().type(`y`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "y"); - cy.get(cesc("#\\/cr1")).should("have.text", "y"); - cy.get(cesc("#\\/sr1")).should("have.text", "bye"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["bye"]); - expect(stateVariables[textinputName].stateValues.value).eq("y"); - }); - - cy.log("Submit answer"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "y"); - cy.get(cesc("#\\/cr1")).should("have.text", "y"); - cy.get(cesc("#\\/sr1")).should("have.text", "y"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["y"]); - expect(stateVariables[textinputName].stateValues.value).eq("y"); - }); - }); - }); - - it("answer multiple awards, set to text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello therebye

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter partially correct answer"); - cy.get(textinputAnchor).clear().type(`bye`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(cesc("#\\/cr1")).should("have.text", "bye"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["bye"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "bye", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(cesc("#\\/cr1")).should("have.text", "bye"); - cy.get(cesc("#\\/sr1")).should("have.text", "bye"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["bye"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["bye"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "bye", - ); - }); - - cy.log("Enter incorrect answer"); - cy.get(textinputAnchor).clear().type(`y`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "y"); - cy.get(cesc("#\\/cr1")).should("have.text", "y"); - cy.get(cesc("#\\/sr1")).should("have.text", "bye"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["bye"]); - expect(stateVariables[textinputName].stateValues.value).eq("y"); - }); - - cy.log("Submit answer"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "y"); - cy.get(cesc("#\\/cr1")).should("have.text", "y"); - cy.get(cesc("#\\/sr1")).should("have.text", "y"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["y"]); - expect(stateVariables[textinputName].stateValues.value).eq("y"); - }); - }); - }); - - it("answer multiple string awards, set to text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello therebye

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(cesc("#\\/cr1")).should("have.text", ""); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([""]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq(""); - }); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(` hello there `).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", ""); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Press enter to submit"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", " hello there "); - cy.get(cesc("#\\/cr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([" hello there "]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - " hello there ", - ); - }); - - cy.log("Enter partially correct answer"); - cy.get(textinputAnchor).clear().type(`bye`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(cesc("#\\/cr1")).should("have.text", "bye"); - cy.get(cesc("#\\/sr1")).should("have.text", " hello there "); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["bye"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([" hello there "]); - expect(stateVariables[textinputName].stateValues.value).eq( - "bye", - ); - }); - - cy.log("Submit answer"); - cy.get(textinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(cesc("#\\/cr1")).should("have.text", "bye"); - cy.get(cesc("#\\/sr1")).should("have.text", "bye"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["bye"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["bye"]); - expect(stateVariables[textinputName].stateValues.value).eq( - "bye", - ); - }); - - cy.log("Enter incorrect answer"); - cy.get(textinputAnchor).clear().type(`y`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "y"); - cy.get(cesc("#\\/cr1")).should("have.text", "y"); - cy.get(cesc("#\\/sr1")).should("have.text", "bye"); - cy.get(cesc("#\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["bye"]); - expect(stateVariables[textinputName].stateValues.value).eq("y"); - }); - - cy.log("Submit answer"); - cy.get(textinputAnchor).type(`{enter}`); - - cy.log("Test value displayed in browser"); - cy.get(textinputAnchor).should("have.value", "y"); - cy.get(cesc("#\\/cr1")).should("have.text", "y"); - cy.get(cesc("#\\/sr1")).should("have.text", "y"); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["y"]); - expect(stateVariables[textinputName].stateValues.value).eq("y"); - }); - }); - }); - - it("answer multiple awards, namespaces", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -
-

- x+y - x -

-

Current response: $_answer1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved{assignNames="ca1"}

-
- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/s/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(cesc("#\\/s\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/s\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/s\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/s/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/s/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/s/_answer1"].stateValues - .submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/s\\/cr1") + " .mjx-mrow").should( - "have.text", - "x+y", - ); - cy.get(cesc("#\\/s\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/s\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/s\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/s/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/s/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/s/_answer1"].stateValues - .submittedResponses, - ).eqls([]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Press enter to submit"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(cesc("#\\/s\\/sr1") + " .mjx-mrow").should( - "have.text", - "x+y", - ); - cy.get(cesc("#\\/s\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/s\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/s\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/s/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/s/_answer1"].stateValues.currentResponses, - ).eqls([["+", "x", "y"]]); - expect( - stateVariables["/s/_answer1"].stateValues - .submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Enter partially correct answer"); - cy.get(mathinputAnchor) - .type( - `{rightarrow}{rightarrow}{rightarrow}{backspace}{backspace}`, - { - force: true, - }, - ) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/s\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/s\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/s\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc("#\\/s\\/ca1")).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/s/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/s/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/s/_answer1"].stateValues - .submittedResponses, - ).eqls([["+", "x", "y"]]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls(['+', 'x', 'y']); - }); - - cy.log("Submit answer"); - cy.get(mathinputSubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(cesc("#\\/s\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/s\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/s\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/s\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/s/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/s/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/s/_answer1"].stateValues - .submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "x", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - - cy.log("Enter incorrect answer"); - cy.get(mathinputAnchor) - .type(`{rightarrow}{backspace}y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'y'); - cy.get(cesc("#\\/s\\/cr1") + " .mjx-mrow").should("have.text", "y"); - cy.get(cesc("#\\/s\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/s\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/s\\/ca1")).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/s/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/s/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/s/_answer1"].stateValues - .submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "y", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('x'); - }); - - cy.log("Submit answer"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - - cy.log("Test value displayed in browser"); - // cy.get(mathinputAnchor).should('have.value', 'y'); - cy.get(cesc("#\\/s\\/sr1") + " .mjx-mrow").should("have.text", "y"); - cy.get(cesc("#\\/s\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/s\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/s\\/ca1")).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/s/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/s/_answer1"].stateValues.currentResponses, - ).eqls(["y"]); - expect( - stateVariables["/s/_answer1"].stateValues - .submittedResponses, - ).eqls(["y"]); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "y", - ); - // expect(stateVariables[mathinputName].stateValues.submittedValue).eqls('y'); - }); - }); - }); - - it("full answer tag", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter values that sum to 3x: - - $_mathinput1.immediateValue{isResponse}+$_mathinput2.immediateValue{isResponse} = 3x - $_mathinput1.immediateValue+$_mathinput2.immediateValue = 3 -

-

First current response: $_answer1.currentResponse{assignNames="cr"}

-

First current response again: $_answer1.currentResponse1{assignNames="cr1"}

-

Second current response: $_answer1.currentResponse2{assignNames="cr2"}

-

Both current responses together: $_answer1.currentResponses{assignNames="crsa crsb"}

-

First submitted response:

-

First submitted response again:

-

Second submitted response:

-

Both submitted responses together: $_answer1.submittedResponses{assignNames="srsa srsb"}

-

Credit for submitted responses: $_answer1.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', ''); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', ''); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - // cy.get(cesc(`#\\/srsa`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - // cy.get(cesc(`#\\/srsb`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F", "\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("\uFF3F"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("\uFF3F"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(undefined); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(undefined); - expect(stateVariables["/_mathinput1"].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/_mathinput2"].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/cr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/cr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/cr2"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/crsa"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/crsb"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr2"].stateValues.value).eq("\uFF3F"); - // expect(stateVariables['/srsa'].stateValues.value).eq('\uFF3F') - // expect(stateVariables['/srsb'].stateValues.value).eq('\uFF3F') - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - - cy.log("Enter a correct answer in"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`x+y`, { force: true }) - .blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type(`2x-y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+y", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "2xβˆ’y", - ); - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/crsa`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("contain.text", "2xβˆ’y"); - cy.get(cesc(`#\\/crsb`) + ` .mjx-mrow`).should("contain.text", "2xβˆ’y"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2xβˆ’y", - ); - }); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - // cy.get(cesc(`#\\/srsa`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - // cy.get(cesc(`#\\/srsb`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(undefined); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(undefined); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/cr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/sr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr2"].stateValues.value).eq("\uFF3F"); - // expect(stateVariables['/srsa'].stateValues.value).eq('\uFF3F') - // expect(stateVariables['/srsb'].stateValues.value).eq('\uFF3F') - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/srsa`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("contain.text", "2xβˆ’y"); - cy.get(cesc(`#\\/srsb`) + ` .mjx-mrow`).should("contain.text", "2xβˆ’y"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2xβˆ’y", - ); - }); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls(["+", 'x', 'y']); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", ['*', 2, 'x'], ['-', 'y']]); - expect(stateVariables["/cr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Enter partially correct answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type(`{ctrl+home}{shift+end}{backspace}3-x`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "3βˆ’x", - ); - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/crsa`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("contain.text", "3βˆ’x"); - cy.get(cesc(`#\\/crsb`) + ` .mjx-mrow`).should("contain.text", "3βˆ’x"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3βˆ’x", - ); - }); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("x"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls(["+", 'x', 'y']); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", ['*', 2, 'x'], ['-', 'y']]); - expect(stateVariables["/cr"].stateValues.value).eqls("x"); - expect(stateVariables["/cr1"].stateValues.value).eqls("x"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("x"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/srsa`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("contain.text", "3βˆ’x"); - cy.get(cesc(`#\\/srsb`) + ` .mjx-mrow`).should("contain.text", "3βˆ’x"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3βˆ’x", - ); - }); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("x"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('x'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("x"); - expect(stateVariables["/cr1"].stateValues.value).eqls("x"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("x"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("x"); - expect(stateVariables["/sr1"].stateValues.value).eqls("x"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("x"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Enter incorrect answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`{rightarrow}{backspace}y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "y", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "3βˆ’x", - ); - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("contain.text", "y"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("contain.text", "y"); - cy.get(cesc(`#\\/crsa`) + ` .mjx-mrow`).should("contain.text", "y"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("contain.text", "3βˆ’x"); - cy.get(cesc(`#\\/crsb`) + ` .mjx-mrow`).should("contain.text", "3βˆ’x"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("y"); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3βˆ’x", - ); - }); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("y"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('x'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("y"); - expect(stateVariables["/cr1"].stateValues.value).eqls("y"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("y"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("x"); - expect(stateVariables["/sr1"].stateValues.value).eqls("x"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("x"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("contain.text", "y"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("contain.text", "y"); - cy.get(cesc(`#\\/srsa`) + ` .mjx-mrow`).should("contain.text", "y"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("contain.text", "3βˆ’x"); - cy.get(cesc(`#\\/srsb`) + ` .mjx-mrow`).should("contain.text", "3βˆ’x"); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("y"); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3βˆ’x", - ); - }); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("y"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('y'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("y"); - expect(stateVariables["/cr1"].stateValues.value).eqls("y"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("y"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("y"); - expect(stateVariables["/sr1"].stateValues.value).eqls("y"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("y"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - }); - - it("full answer tag, two inputs inside answer, shorter form", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter values that sum to 3x: - - - $_mathinput1+$_mathinput2 = 3x - $_mathinput1+$_mathinput2 = 3 -

-

First current response: $_answer1.currentResponse{assignNames="cr"}

-

First current response again: $_answer1.currentResponse1{assignNames="cr1"}

-

Second current response: $_answer1.currentResponse2{assignNames="cr2"}

-

Both current responses together: $_answer1.currentResponses{assignNames="crsa crsb"}

-

First submitted response:

-

First submitted response again:

-

Second submitted response:

-

Both submitted responses together: $_answer1.submittedResponses{assignNames="srsa srsb"}

-

Credit for submitted responses: $_answer1.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', ''); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', ''); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - // cy.get(cesc(`#\\/srsa`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - // cy.get(cesc(`#\\/srsb`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F", "\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("\uFF3F"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("\uFF3F"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(undefined); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(undefined); - expect(stateVariables["/_mathinput1"].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/_mathinput2"].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/cr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/cr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/cr2"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/crsa"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/crsb"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr2"].stateValues.value).eq("\uFF3F"); - // expect(stateVariables['/srsa'].stateValues.value).eq('\uFF3F') - // expect(stateVariables['/srsb'].stateValues.value).eq('\uFF3F') - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - - cy.log("Enter a correct answer in"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`x+y`, { force: true }) - .blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type(`2x-y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'x+y'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '2x-y'); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "x+y"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "x+y"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("have.text", "2xβˆ’y"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - // cy.get(cesc(`#\\/srsa`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - // cy.get(cesc(`#\\/srsb`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(undefined); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(undefined); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/cr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/sr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr2"].stateValues.value).eq("\uFF3F"); - // expect(stateVariables['/srsa'].stateValues.value).eq('\uFF3F') - // expect(stateVariables['/srsb'].stateValues.value).eq('\uFF3F') - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'x+y'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '2x-y'); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "x+y"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "x+y"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("have.text", "2xβˆ’y"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls(["+", 'x', 'y']); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", ['*', 2, 'x'], ['-', 'y']]); - expect(stateVariables["/cr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Enter partially correct answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type(`{ctrl+home}{shift+end}{backspace}3-x`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'x'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '3-x'); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "x"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "x"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("have.text", "3βˆ’x"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("x"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls(["+", 'x', 'y']); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", ['*', 2, 'x'], ['-', 'y']]); - expect(stateVariables["/cr"].stateValues.value).eqls("x"); - expect(stateVariables["/cr1"].stateValues.value).eqls("x"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("x"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'x'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '3-x'); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "x"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "x"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("have.text", "3βˆ’x"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("x"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('x'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("x"); - expect(stateVariables["/cr1"].stateValues.value).eqls("x"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("x"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("x"); - expect(stateVariables["/sr1"].stateValues.value).eqls("x"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("x"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Enter incorrect answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`{rightarrow}{backspace}y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'y'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '3-x'); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "y"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "y"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("have.text", "3βˆ’x"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("y"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('x'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("y"); - expect(stateVariables["/cr1"].stateValues.value).eqls("y"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("y"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("x"); - expect(stateVariables["/sr1"].stateValues.value).eqls("x"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("x"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'y'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '3-x'); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "y"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "y"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("have.text", "3βˆ’x"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("y"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('y'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("y"); - expect(stateVariables["/cr1"].stateValues.value).eqls("y"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("y"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("y"); - expect(stateVariables["/sr1"].stateValues.value).eqls("y"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("y"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - }); - - it("full answer tag, copied in awards, shorter form", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $_mathinput1+$_mathinput2 = 3x - $_mathinput1+$_mathinput2 = 3 - - -

Enter values that sum to 3x: - - - - -

-

First current response: $_answer1.currentResponse{assignNames="cr"}

-

First current response again: $_answer1.currentResponse1{assignNames="cr1"}

-

Second current response: $_answer1.currentResponse2{assignNames="cr2"}

-

Both current responses together: $_answer1.currentResponses{assignNames="crsa crsb"}

-

First submitted response:

-

First submitted response again:

-

Second submitted response:

-

Both submitted responses together: $_answer1.submittedResponses{assignNames="srsa srsb"}

-

Credit for submitted responses: $_answer1.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', ''); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', ''); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - // cy.get(cesc(`#\\/srsa`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - // cy.get(cesc(`#\\/srsb`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F", "\uFF3F"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("\uFF3F"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("\uFF3F"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(undefined); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(undefined); - expect(stateVariables["/_mathinput1"].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/_mathinput2"].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/cr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/cr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/cr2"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/crsa"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/crsb"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr2"].stateValues.value).eq("\uFF3F"); - // expect(stateVariables['/srsa'].stateValues.value).eq('\uFF3F') - // expect(stateVariables['/srsb'].stateValues.value).eq('\uFF3F') - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - - cy.log("Enter a correct answer in"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`x+y`, { force: true }) - .blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type(`2x-y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'x+y'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '2x-y'); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "x+y"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "x+y"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("have.text", "2xβˆ’y"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - // cy.get(cesc(`#\\/srsa`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - // cy.get(cesc(`#\\/srsb`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('οΌΏ') - // }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(undefined); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(undefined); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/cr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/sr"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr1"].stateValues.value).eq("\uFF3F"); - expect(stateVariables["/sr2"].stateValues.value).eq("\uFF3F"); - // expect(stateVariables['/srsa'].stateValues.value).eq('\uFF3F') - // expect(stateVariables['/srsb'].stateValues.value).eq('\uFF3F') - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'x+y'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '2x-y'); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "x+y"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "x+y"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("have.text", "2xβˆ’y"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls(["+", 'x', 'y']); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", ['*', 2, 'x'], ['-', 'y']]); - expect(stateVariables["/cr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Enter partially correct answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type(`{ctrl+home}{shift+end}{backspace}3-x`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'x'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '3-x'); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "x"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "x"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("have.text", "3βˆ’x"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xβˆ’y"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([ - ["+", "x", "y"], - ["+", ["*", 2, "x"], ["-", "y"]], - ]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(["+", "x", "y"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", ["*", 2, "x"], ["-", "y"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("x"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls(["+", 'x', 'y']); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", ['*', 2, 'x'], ['-', 'y']]); - expect(stateVariables["/cr"].stateValues.value).eqls("x"); - expect(stateVariables["/cr1"].stateValues.value).eqls("x"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("x"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["-", "y"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'x'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '3-x'); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "x"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "x"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("have.text", "3βˆ’x"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("x"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('x'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("x"); - expect(stateVariables["/cr1"].stateValues.value).eqls("x"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("x"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("x"); - expect(stateVariables["/sr1"].stateValues.value).eqls("x"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("x"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Enter incorrect answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`{rightarrow}{backspace}y`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'y'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '3-x'); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "y"); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "y"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("have.text", "3βˆ’x"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["x", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("x"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("y"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('x'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("y"); - expect(stateVariables["/cr1"].stateValues.value).eqls("y"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("y"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("x"); - expect(stateVariables["/sr1"].stateValues.value).eqls("x"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("x"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', 'y'); - // cy.get(cesc('#\\/_mathinput2_input')).should('have.value', '3-x'); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "y"); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "y"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("have.text", "3βˆ’x"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/crsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/crsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/srsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/srsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3βˆ’x"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["y", ["+", 3, ["-", "x"]]]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("y"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(["+", 3, ["-", "x"]]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls("y"); - // expect(stateVariables['/_mathinput1'].stateValues.submittedValue).eqls('y'); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - // expect(stateVariables['/_mathinput2'].stateValues.submittedValue).eqls(["+", 3, ['-', 'x']]); - expect(stateVariables["/cr"].stateValues.value).eqls("y"); - expect(stateVariables["/cr1"].stateValues.value).eqls("y"); - expect(stateVariables["/cr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/crsa"].stateValues.value).eqls("y"); - expect(stateVariables["/crsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/sr"].stateValues.value).eqls("y"); - expect(stateVariables["/sr1"].stateValues.value).eqls("y"); - expect(stateVariables["/sr2"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/srsa"].stateValues.value).eqls("y"); - expect(stateVariables["/srsb"].stateValues.value).eqls([ - "+", - 3, - ["-", "x"], - ]); - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - }); - - it("full answer tag, text inputs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter rain and snow in either order: - - $_textinput1.immediateValue{isResponse} $_textinput2.immediateValue{isResponse} = rain snow - $_textinput1.immediateValue $_textinput2.immediateValue = snow rain - $_textinput1.immediateValue = rain - $_textinput1.immediateValue = snow - $_textinput2.immediateValue = rain - $_textinput2.immediateValue = snow -

-

First current response: $_answer1.currentResponse{assignNames="cr"}

-

First current response again: $_answer1.currentResponse1{assignNames="cr1"}

-

Second current response: $_answer1.currentResponse2{assignNames="cr2"}

-

Both current responses together: $_answer1.currentResponses{assignNames="crsa crsb"}

-

First submitted response:

-

First submitted response again:

-

Second submitted response:

-

Both submitted responses together: $_answer1.submittedResponses{assignNames="srsa srsb"}

-

Credit for submitted responses: $_answer1.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", ""); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", ""); - - cy.get(cesc(`#\\/cr`)).should("have.text", ""); - cy.get(cesc(`#\\/cr1`)).should("have.text", ""); - cy.get(cesc(`#\\/cr2`)).should("have.text", ""); - cy.get(cesc(`#\\/crsa`)).should("have.text", ""); - cy.get(cesc(`#\\/crsb`)).should("have.text", ""); - cy.get(cesc(`#\\/sr`)).should("have.text", ""); - cy.get(cesc(`#\\/sr1`)).should("have.text", ""); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - // cy.get(cesc(`#\\/srsa`)).should('have.text', 'οΌΏ') - // cy.get(cesc(`#\\/srsb`)).should('have.text', 'οΌΏ') - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["", ""]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls(""); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls(""); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(undefined); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(undefined); - expect(stateVariables["/_textinput1"].stateValues.value).eq(""); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/_textinput2"].stateValues.value).eq(""); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/cr"].stateValues.value).eq(""); - expect(stateVariables["/cr1"].stateValues.value).eq(""); - expect(stateVariables["/cr2"].stateValues.value).eq(""); - expect(stateVariables["/crsa"].stateValues.value).eq(""); - expect(stateVariables["/crsb"].stateValues.value).eq(""); - expect(stateVariables["/sr"].stateValues.value).eq(""); - expect(stateVariables["/sr1"].stateValues.value).eq(""); - expect(stateVariables["/sr2"].stateValues.value).eq(""); - // expect(stateVariables['/srsa'].stateValues.value).eq('\uFF3F') - // expect(stateVariables['/srsb'].stateValues.value).eq('\uFF3F') - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - - cy.log("Enter a correct answer in"); - cy.get(cesc("#\\/_textinput1_input")).type(`rain`).blur(); - cy.get(cesc("#\\/_textinput2_input")).type(`snow{enter}`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "rain"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "rain"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "snow"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "rain"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr`)).should("have.text", ""); - cy.get(cesc(`#\\/sr1`)).should("have.text", ""); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - // cy.get(cesc(`#\\/srsa`)).should('have.text', 'οΌΏ') - // cy.get(cesc(`#\\/srsb`)).should('have.text', 'οΌΏ') - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["rain", "snow"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls(undefined); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls(undefined); - expect(stateVariables["/_textinput1"].stateValues.value).eq("rain"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("snow"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('\uFF3F'); - expect(stateVariables["/cr"].stateValues.value).eq("rain"); - expect(stateVariables["/cr1"].stateValues.value).eq("rain"); - expect(stateVariables["/cr2"].stateValues.value).eq("snow"); - expect(stateVariables["/crsa"].stateValues.value).eq("rain"); - expect(stateVariables["/crsb"].stateValues.value).eq("snow"); - expect(stateVariables["/sr"].stateValues.value).eq(""); - expect(stateVariables["/sr1"].stateValues.value).eq(""); - expect(stateVariables["/sr2"].stateValues.value).eq(""); - // expect(stateVariables['/srsa'].stateValues.value).eq('\uFF3F') - // expect(stateVariables['/srsb'].stateValues.value).eq('\uFF3F') - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "rain"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "rain"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "snow"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "rain"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "snow"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "rain"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "snow"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["rain", "snow"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["rain", "snow"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("snow"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("rain"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('rain'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("snow"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('snow'); - expect(stateVariables["/cr"].stateValues.value).eq("rain"); - expect(stateVariables["/cr1"].stateValues.value).eq("rain"); - expect(stateVariables["/cr2"].stateValues.value).eq("snow"); - expect(stateVariables["/crsa"].stateValues.value).eq("rain"); - expect(stateVariables["/crsb"].stateValues.value).eq("snow"); - expect(stateVariables["/sr"].stateValues.value).eq("rain"); - expect(stateVariables["/sr1"].stateValues.value).eq("rain"); - expect(stateVariables["/sr2"].stateValues.value).eq("snow"); - expect(stateVariables["/srsa"].stateValues.value).eq("rain"); - expect(stateVariables["/srsb"].stateValues.value).eq("snow"); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Enter partially correct answer"); - cy.get(cesc("#\\/_textinput2_input")).clear().type(`rain`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "rain"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "rain"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "rain"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "rain"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "rain"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "snow"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "rain"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "snow"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.wait(100); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["rain", "rain"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["rain", "snow"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("snow"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("rain"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('rain'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("rain"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('snow'); - expect(stateVariables["/cr"].stateValues.value).eq("rain"); - expect(stateVariables["/cr1"].stateValues.value).eq("rain"); - expect(stateVariables["/cr2"].stateValues.value).eq("rain"); - expect(stateVariables["/crsa"].stateValues.value).eq("rain"); - expect(stateVariables["/crsb"].stateValues.value).eq("rain"); - expect(stateVariables["/sr"].stateValues.value).eq("rain"); - expect(stateVariables["/sr1"].stateValues.value).eq("rain"); - expect(stateVariables["/sr2"].stateValues.value).eq("snow"); - expect(stateVariables["/srsa"].stateValues.value).eq("rain"); - expect(stateVariables["/srsb"].stateValues.value).eq("snow"); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "rain"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "rain"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "rain"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "rain"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "rain"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "rain"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "rain"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "rain"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["rain", "rain"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["rain", "rain"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("rain"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("rain"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('rain'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("rain"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('rain'); - expect(stateVariables["/cr"].stateValues.value).eq("rain"); - expect(stateVariables["/cr1"].stateValues.value).eq("rain"); - expect(stateVariables["/cr2"].stateValues.value).eq("rain"); - expect(stateVariables["/crsa"].stateValues.value).eq("rain"); - expect(stateVariables["/crsb"].stateValues.value).eq("rain"); - expect(stateVariables["/sr"].stateValues.value).eq("rain"); - expect(stateVariables["/sr1"].stateValues.value).eq("rain"); - expect(stateVariables["/sr2"].stateValues.value).eq("rain"); - expect(stateVariables["/srsa"].stateValues.value).eq("rain"); - expect(stateVariables["/srsb"].stateValues.value).eq("rain"); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Make correct again"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`snow`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "rain"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "snow"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "snow"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "rain"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "snow"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "rain"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "rain"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "rain"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.wait(100); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["snow", "rain"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["rain", "rain"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("rain"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("snow"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('rain'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("rain"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('rain'); - expect(stateVariables["/cr"].stateValues.value).eq("snow"); - expect(stateVariables["/cr1"].stateValues.value).eq("snow"); - expect(stateVariables["/cr2"].stateValues.value).eq("rain"); - expect(stateVariables["/crsa"].stateValues.value).eq("snow"); - expect(stateVariables["/crsb"].stateValues.value).eq("rain"); - expect(stateVariables["/sr"].stateValues.value).eq("rain"); - expect(stateVariables["/sr1"].stateValues.value).eq("rain"); - expect(stateVariables["/sr2"].stateValues.value).eq("rain"); - expect(stateVariables["/srsa"].stateValues.value).eq("rain"); - expect(stateVariables["/srsb"].stateValues.value).eq("rain"); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "rain"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "snow"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "snow"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "rain"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "snow"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "rain"); - cy.get(cesc(`#\\/sr`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "rain"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "snow"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "rain"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["snow", "rain"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("rain"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["snow", "rain"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("rain"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("snow"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('snow'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("rain"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('rain'); - expect(stateVariables["/cr"].stateValues.value).eq("snow"); - expect(stateVariables["/cr1"].stateValues.value).eq("snow"); - expect(stateVariables["/cr2"].stateValues.value).eq("rain"); - expect(stateVariables["/crsa"].stateValues.value).eq("snow"); - expect(stateVariables["/crsb"].stateValues.value).eq("rain"); - expect(stateVariables["/sr"].stateValues.value).eq("snow"); - expect(stateVariables["/sr1"].stateValues.value).eq("snow"); - expect(stateVariables["/sr2"].stateValues.value).eq("rain"); - expect(stateVariables["/srsa"].stateValues.value).eq("snow"); - expect(stateVariables["/srsb"].stateValues.value).eq("rain"); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Enter another partially correct answer"); - cy.get(cesc("#\\/_textinput2_input")).clear().type(`snow`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "snow"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "snow"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "snow"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "snow"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "rain"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "snow"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "rain"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.wait(100); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["snow", "snow"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["snow", "rain"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("rain"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("snow"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('snow'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("snow"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('rain'); - expect(stateVariables["/cr"].stateValues.value).eq("snow"); - expect(stateVariables["/cr1"].stateValues.value).eq("snow"); - expect(stateVariables["/cr2"].stateValues.value).eq("snow"); - expect(stateVariables["/crsa"].stateValues.value).eq("snow"); - expect(stateVariables["/crsb"].stateValues.value).eq("snow"); - expect(stateVariables["/sr"].stateValues.value).eq("snow"); - expect(stateVariables["/sr1"].stateValues.value).eq("snow"); - expect(stateVariables["/sr2"].stateValues.value).eq("rain"); - expect(stateVariables["/srsa"].stateValues.value).eq("snow"); - expect(stateVariables["/srsb"].stateValues.value).eq("rain"); - expect(stateVariables["/ca"].stateValues.value).eq(1); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "snow"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "snow"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "snow"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "snow"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "snow"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "snow"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "snow"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["snow", "snow"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["snow", "snow"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("snow"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("snow"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('snow'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("snow"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('snow'); - expect(stateVariables["/cr"].stateValues.value).eq("snow"); - expect(stateVariables["/cr1"].stateValues.value).eq("snow"); - expect(stateVariables["/cr2"].stateValues.value).eq("snow"); - expect(stateVariables["/crsa"].stateValues.value).eq("snow"); - expect(stateVariables["/crsb"].stateValues.value).eq("snow"); - expect(stateVariables["/sr"].stateValues.value).eq("snow"); - expect(stateVariables["/sr1"].stateValues.value).eq("snow"); - expect(stateVariables["/sr2"].stateValues.value).eq("snow"); - expect(stateVariables["/srsa"].stateValues.value).eq("snow"); - expect(stateVariables["/srsb"].stateValues.value).eq("snow"); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Enter incorrect answer"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`fog`).blur(); - cy.get(cesc("#\\/_textinput2_input")).clear().type(`hail`).blur(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "fog"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "hail"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "fog"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "fog"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hail"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "fog"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "hail"); - cy.get(cesc(`#\\/sr`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "snow"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "snow"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "snow"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "snow"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.wait(100); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["fog", "hail"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("fog"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("hail"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["snow", "snow"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("snow"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("snow"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("fog"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('snow'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("hail"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('snow'); - expect(stateVariables["/cr"].stateValues.value).eq("fog"); - expect(stateVariables["/cr1"].stateValues.value).eq("fog"); - expect(stateVariables["/cr2"].stateValues.value).eq("hail"); - expect(stateVariables["/crsa"].stateValues.value).eq("fog"); - expect(stateVariables["/crsb"].stateValues.value).eq("hail"); - expect(stateVariables["/sr"].stateValues.value).eq("snow"); - expect(stateVariables["/sr1"].stateValues.value).eq("snow"); - expect(stateVariables["/sr2"].stateValues.value).eq("snow"); - expect(stateVariables["/srsa"].stateValues.value).eq("snow"); - expect(stateVariables["/srsb"].stateValues.value).eq("snow"); - expect(stateVariables["/ca"].stateValues.value).eq(0.5); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "fog"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "hail"); - - cy.get(cesc(`#\\/cr`)).should("have.text", "fog"); - cy.get(cesc(`#\\/cr1`)).should("have.text", "fog"); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hail"); - cy.get(cesc(`#\\/crsa`)).should("have.text", "fog"); - cy.get(cesc(`#\\/crsb`)).should("have.text", "hail"); - cy.get(cesc(`#\\/sr`)).should("have.text", "fog"); - cy.get(cesc(`#\\/sr1`)).should("have.text", "fog"); - cy.get(cesc(`#\\/sr2`)).should("have.text", "hail"); - cy.get(cesc(`#\\/srsa`)).should("have.text", "fog"); - cy.get(cesc(`#\\/srsb`)).should("have.text", "hail"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["fog", "hail"]); - expect( - stateVariables["/_answer1"].stateValues.currentResponse1, - ).eqls("fog"); - expect( - stateVariables["/_answer1"].stateValues.currentResponse2, - ).eqls("hail"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["fog", "hail"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse1, - ).eqls("fog"); - expect( - stateVariables["/_answer1"].stateValues.submittedResponse2, - ).eqls("hail"); - expect(stateVariables["/_textinput1"].stateValues.value).eq("fog"); - // expect(stateVariables['/_textinput1'].stateValues.submittedValue).eq('fog'); - expect(stateVariables["/_textinput2"].stateValues.value).eq("hail"); - // expect(stateVariables['/_textinput2'].stateValues.submittedValue).eq('hail'); - expect(stateVariables["/cr"].stateValues.value).eq("fog"); - expect(stateVariables["/cr1"].stateValues.value).eq("fog"); - expect(stateVariables["/cr2"].stateValues.value).eq("hail"); - expect(stateVariables["/crsa"].stateValues.value).eq("fog"); - expect(stateVariables["/crsb"].stateValues.value).eq("hail"); - expect(stateVariables["/sr"].stateValues.value).eq("fog"); - expect(stateVariables["/sr1"].stateValues.value).eq("fog"); - expect(stateVariables["/sr2"].stateValues.value).eq("hail"); - expect(stateVariables["/srsa"].stateValues.value).eq("fog"); - expect(stateVariables["/srsb"].stateValues.value).eq("hail"); - expect(stateVariables["/ca"].stateValues.value).eq(0); - }); - }); - - it("answer inequalities", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - Enter enter number larger than 5 or less than 2: - - - $m > 5 - $m < 2 - -

Submitted response: $_answer1.submittedResponse{assignNames="sr"}

-

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

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test initial values"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Submit a correct answer"); - cy.get(cesc("#\\/m") + " textarea").type(`6`, { force: true }); - cy.get(cesc("#\\/m_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "6"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Submit an incorrect answer"); - cy.get(cesc("#\\/m") + " textarea").type(`{rightarrow}{backspace}5`, { - force: true, - }); - cy.get(cesc("#\\/m_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "5"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.log("Submit a different correct answer"); - cy.get(cesc("#\\/m") + " textarea").type(`{rightarrow}{backspace}-3`, { - force: true, - }); - cy.get(cesc("#\\/m_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "βˆ’3"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Submit a correct answer that must be simplified"); - cy.get(cesc("#\\/m") + " textarea").type( - `{end}{backspace}{backspace}5xy-5xy+9`, - { force: true }, - ); - cy.get(cesc("#\\/m_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "5xyβˆ’5xy+9"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.log("Submit a non-numerical answer"); - cy.get(cesc("#\\/m") + " textarea").type( - `{end}{leftarrow}{leftarrow}z`, - { - force: true, - }, - ); - cy.get(cesc("#\\/m_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "5xyβˆ’5xyz+9"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - }); - - it("answer extended inequalities", () => { - cy.log("Number between -1 and 1, inclusive"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -1 <= $_mathinput1.immediateValue{isResponse} <= 1 - -

Submitted response: $_answer1.submittedResponse{assignNames="sr"}

-

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

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', ''); - - let answers1 = { - 1: "1", - "-1": "1", - 0.5: "1", - 1.1: "0", - "-2": "0", - "x-x": "1", - x: "0", - }; - - for (let answerString in answers1) { - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}" + answerString, - { delay: 5, force: true }, - ); - cy.get(cesc("#\\/_mathinput1_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should( - "have.text", - answerString.replace(/-/g, "βˆ’"), - ); - cy.get(cesc(`#\\/ca`)).should("have.text", answers1[answerString]); - } - - cy.wait(500); - - cy.log("Number between -1 and 1, exclusive"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b - - -1 < $_mathinput1.immediateValue{isResponse} < 1 - -

Submitted response: $_answer1.submittedResponse{assignNames="sr"}

-

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

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "b"); // to wait until loaded - - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', ''); - - let answers2 = { - 1: "0", - "-1": "0", - 0.5: "1", - 0.99: "1", - "-2": "0", - "x-x": "1", - x: "0", - }; - for (let answerString in answers2) { - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}" + answerString, - { delay: 5, force: true }, - ); - cy.get(cesc("#\\/_mathinput1_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should( - "have.text", - answerString.replace(/-/g, "βˆ’"), - ); - cy.get(cesc(`#\\/ca`)).should("have.text", answers2[answerString]); - } - - cy.wait(500); - - cy.log("Number between -1 and 1, as greater than"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c - - 1 > $_mathinput1.immediateValue{isResponse} >= -1 - -

Submitted response: $_answer1.submittedResponse{assignNames="sr"}

-

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

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "c"); // to wait until loaded - - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', ''); - - let answers3 = { - 1: "0", - "-1": "1", - 0.5: "1", - 0.99: "1", - "-2": "0", - "x-x": "1", - x: "0", - }; - - for (let answerString in answers3) { - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}" + answerString, - { delay: 5, force: true }, - ); - cy.get(cesc("#\\/_mathinput1_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should( - "have.text", - answerString.replace(/-/g, "βˆ’"), - ); - cy.get(cesc(`#\\/ca`)).should("have.text", answers3[answerString]); - } - }); - - it("compound logic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - (($_mathinput1.immediateValue{isResponse} = x - and $_mathinput2.immediateValue{isResponse} != $_mathinput1.immediateValue) - or - ($_mathinput1.immediateValue = y - and $_mathinput2.immediateValue != z - and $_mathinput2.immediateValue != q)) - and $_mathinput3.immediateValue{isResponse} > 5 - - -

Submitted responses: $_answer1.submittedResponses{assignNames="sr1 sr2 sr3"}

-

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

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // cy.get(cesc('#\\/_mathinput1_input')).should('have.value', ''); - - let answers1 = [ - ["1", "x", "z", "6"], - ["0", "x", "x", "6"], - ["0", "x", "z", "5"], - ["1", "y", "y", "7"], - ["0", "y", "z", "7"], - ["0", "y", "q", "7"], - ["1", "y", "y^2", "7"], - ["0", "y", "y", "a"], - ]; - - for (let answer of answers1) { - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type("{end}{backspace}" + answer[1], { delay: 5, force: true }) - .blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type("{ctrl+home}{shift+end}{backspace}" + answer[2], { - delay: 5, - force: true, - }) - .blur(); - cy.get(cesc("#\\/_mathinput3") + " textarea") - .type("{end}{backspace}" + answer[3], { delay: 5, force: true }) - .blur(); - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should( - "have.text", - answer[1], - ); - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should( - "contain.text", - answer[2].replace("^", ""), - ); - cy.get(cesc("#\\/sr3") + " .mjx-mrow").should( - "have.text", - answer[3], - ); - - cy.get(cesc("#\\/ca")).should("have.text", answer[0]); - } - }); - - it("answer inside map", () => { - 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(); - - let mathinput1Name = - stateVariables["/a/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinput1Anchor = cesc2("#" + mathinput1Name) + " textarea"; - let mathinput1SubmitAnchor = cesc2( - "#" + mathinput1Name + "_submit", - ); - - let mathinput2Name = - stateVariables["/b/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - let mathinput2SubmitAnchor = cesc2( - "#" + mathinput2Name + "_submit", - ); - - let mathinput3Name = - stateVariables["/c/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinput3Anchor = cesc2("#" + mathinput3Name) + " textarea"; - let mathinput3SubmitAnchor = cesc2( - "#" + mathinput3Name + "_submit", - ); - - cy.log("Test value displayed in browser"); - // cy.get(mathinput1Anchor).should('have.value', ''); - // cy.get(mathinput2Anchor).should('have.value', ''); - // cy.get(mathinput3Anchor).should('have.value', ''); - cy.get(cesc("#\\/a\\/ca")).should("have.text", "0"); - cy.get(cesc("#\\/b\\/ca")).should("have.text", "0"); - cy.get(cesc("#\\/c\\/ca")).should("have.text", "0"); - cy.get(cesc("#\\/a\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/b\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/c\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/a\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/b\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/c\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/a/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/a/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/a/_answer1"].stateValues - .submittedResponses, - ).eqls([]); - expect(stateVariables[mathinput1Name].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinput1Name].stateValues.submittedValue).eq('\uFF3F'); - expect( - stateVariables["/b/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/b/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/b/_answer1"].stateValues - .submittedResponses, - ).eqls([]); - expect(stateVariables[mathinput2Name].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinput2Name].stateValues.submittedValue).eq('\uFF3F'); - expect( - stateVariables["/c/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/c/_answer1"].stateValues.currentResponses, - ).eqls(["\uFF3F"]); - expect( - stateVariables["/c/_answer1"].stateValues - .submittedResponses, - ).eqls([]); - expect(stateVariables[mathinput3Name].stateValues.value).eq( - "\uFF3F", - ); - // expect(stateVariables[mathinput3Name].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Enter correct answer in all three blanks"); - cy.get(mathinput1Anchor).type(`x`, { force: true }).blur(); - cy.get(mathinput2Anchor).type(`x^2`, { force: true }).blur(); - cy.get(mathinput3Anchor).type(`x^3`, { force: true }).blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinput1Anchor).should('have.value', 'x'); - // cy.get(mathinput2Anchor).should('have.value', 'x^2'); - // cy.get(mathinput3Anchor).should('have.value', 'x^3'); - - cy.get(cesc("#\\/a\\/cr") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/b\\/cr") + " .mjx-mrow").should( - "contain.text", - "x2", - ); - cy.get(cesc("#\\/c\\/cr") + " .mjx-mrow").should( - "contain.text", - "x3", - ); - - cy.get(cesc("#\\/a\\/ca")).should("have.text", "0"); - cy.get(cesc("#\\/b\\/ca")).should("have.text", "0"); - cy.get(cesc("#\\/c\\/ca")).should("have.text", "0"); - cy.get(cesc("#\\/a\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/b\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2"); - }); - cy.get(cesc("#\\/c\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3"); - }); - cy.get(cesc("#\\/a\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/b\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/c\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/a/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/a/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/a/_answer1"].stateValues - .submittedResponses, - ).eqls([]); - expect(stateVariables[mathinput1Name].stateValues.value).eq( - "x", - ); - // expect(stateVariables[mathinput1Name].stateValues.submittedValue).eq('\uFF3F'); - expect( - stateVariables["/b/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/b/_answer1"].stateValues.currentResponses, - ).eqls([["^", "x", 2]]); - expect( - stateVariables["/b/_answer1"].stateValues - .submittedResponses, - ).eqls([]); - expect(stateVariables[mathinput2Name].stateValues.value).eqls([ - "^", - "x", - 2, - ]); - // expect(stateVariables[mathinput2Name].stateValues.submittedValue).eq('\uFF3F'); - expect( - stateVariables["/c/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/c/_answer1"].stateValues.currentResponses, - ).eqls([["^", "x", 3]]); - expect( - stateVariables["/c/_answer1"].stateValues - .submittedResponses, - ).eqls([]); - expect(stateVariables[mathinput3Name].stateValues.value).eqls([ - "^", - "x", - 3, - ]); - // expect(stateVariables[mathinput3Name].stateValues.submittedValue).eq('\uFF3F'); - }); - - cy.log("Submit answers"); - cy.get(mathinput1SubmitAnchor).click(); - cy.get(mathinput2SubmitAnchor).click(); - cy.get(mathinput3SubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinput1Anchor).should('have.value', 'x'); - // cy.get(mathinput2Anchor).should('have.value', 'x^2'); - // cy.get(mathinput3Anchor).should('have.value', 'x^3'); - - cy.get(cesc("#\\/a\\/ca")).should("have.text", "1"); - cy.get(cesc("#\\/b\\/ca")).should("have.text", "1"); - cy.get(cesc("#\\/c\\/ca")).should("have.text", "1"); - cy.get(cesc("#\\/a\\/sr") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/b\\/sr") + " .mjx-mrow").should( - "contain.text", - "x2", - ); - cy.get(cesc("#\\/c\\/sr") + " .mjx-mrow").should( - "contain.text", - "x3", - ); - cy.get(cesc("#\\/a\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/b\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2"); - }); - cy.get(cesc("#\\/c\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3"); - }); - cy.get(cesc("#\\/a\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/b\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2"); - }); - cy.get(cesc("#\\/c\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/a/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/a/_answer1"].stateValues.currentResponses, - ).eqls(["x"]); - expect( - stateVariables["/a/_answer1"].stateValues - .submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinput1Name].stateValues.value).eq( - "x", - ); - // expect(stateVariables[mathinput1Name].stateValues.submittedValue).eq('x'); - expect( - stateVariables["/b/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/b/_answer1"].stateValues.currentResponses, - ).eqls([["^", "x", 2]]); - expect( - stateVariables["/b/_answer1"].stateValues - .submittedResponses, - ).eqls([["^", "x", 2]]); - expect(stateVariables[mathinput2Name].stateValues.value).eqls([ - "^", - "x", - 2, - ]); - // expect(stateVariables[mathinput2Name].stateValues.submittedValue).eqls(['^', 'x', 2]); - expect( - stateVariables["/c/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/c/_answer1"].stateValues.currentResponses, - ).eqls([["^", "x", 3]]); - expect( - stateVariables["/c/_answer1"].stateValues - .submittedResponses, - ).eqls([["^", "x", 3]]); - expect(stateVariables[mathinput3Name].stateValues.value).eqls([ - "^", - "x", - 3, - ]); - // expect(stateVariables[mathinput3Name].stateValues.submittedValue).eqls(['^', 'x', 3]); - }); - - cy.log("Enter wrong answers"); - cy.get(mathinput1Anchor) - .type(`{end}{backspace}u`, { force: true }) - .blur(); - cy.get(mathinput2Anchor) - .type(`{ctrl+home}{shift+end}{backspace}v`, { force: true }) - .blur(); - cy.get(mathinput3Anchor) - .type(`{ctrl+home}{shift+end}{backspace}w`, { force: true }) - .blur(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinput1Anchor).should('have.value', 'u'); - // cy.get(mathinput2Anchor).should('have.value', 'v'); - // cy.get(mathinput3Anchor).should('have.value', 'w'); - - cy.get(cesc("#\\/a\\/cr") + " .mjx-mrow").should("have.text", "u"); - cy.get(cesc("#\\/b\\/cr") + " .mjx-mrow").should("have.text", "v"); - cy.get(cesc("#\\/c\\/cr") + " .mjx-mrow").should("have.text", "w"); - - cy.get(cesc("#\\/a\\/ca")).should("have.text", "1"); - cy.get(cesc("#\\/b\\/ca")).should("have.text", "1"); - cy.get(cesc("#\\/c\\/ca")).should("have.text", "1"); - - cy.get(cesc("#\\/a\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/b\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/c\\/cr") + " .mjx-mrow").should("have.text", "w"); - cy.get(cesc("#\\/c\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("w"); - }); - cy.get(cesc("#\\/a\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/b\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2"); - }); - cy.get(cesc("#\\/c\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/a/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/a/_answer1"].stateValues.currentResponses, - ).eqls(["u"]); - expect( - stateVariables["/a/_answer1"].stateValues - .submittedResponses, - ).eqls(["x"]); - expect(stateVariables[mathinput1Name].stateValues.value).eq( - "u", - ); - // expect(stateVariables[mathinput1Name].stateValues.submittedValue).eq('x'); - expect( - stateVariables["/b/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/b/_answer1"].stateValues.currentResponses, - ).eqls(["v"]); - expect( - stateVariables["/b/_answer1"].stateValues - .submittedResponses, - ).eqls([["^", "x", 2]]); - expect(stateVariables[mathinput2Name].stateValues.value).eq( - "v", - ); - // expect(stateVariables[mathinput2Name].stateValues.submittedValue).eqls(['^', 'x', 2]); - expect( - stateVariables["/c/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/c/_answer1"].stateValues.currentResponses, - ).eqls(["w"]); - expect( - stateVariables["/c/_answer1"].stateValues - .submittedResponses, - ).eqls([["^", "x", 3]]); - expect(stateVariables[mathinput3Name].stateValues.value).eq( - "w", - ); - // expect(stateVariables[mathinput3Name].stateValues.submittedValue).eqls(['^', 'x', 3]); - }); - - cy.log("Submit answers"); - cy.get(mathinput1SubmitAnchor).click(); - cy.get(mathinput2SubmitAnchor).click(); - cy.get(mathinput3SubmitAnchor).click(); - - cy.log("Test value displayed in browser"); - // cy.get(mathinput1Anchor).should('have.value', 'u'); - // cy.get(mathinput2Anchor).should('have.value', 'v'); - // cy.get(mathinput3Anchor).should('have.value', 'w'); - - cy.get(cesc("#\\/a\\/ca")).should("have.text", "0"); - cy.get(cesc("#\\/b\\/ca")).should("have.text", "0"); - cy.get(cesc("#\\/c\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/a\\/sr") + " .mjx-mrow").should("have.text", "u"); - cy.get(cesc("#\\/b\\/sr") + " .mjx-mrow").should("have.text", "v"); - cy.get(cesc("#\\/c\\/sr") + " .mjx-mrow").should("have.text", "w"); - - cy.get(cesc("#\\/a\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/b\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/c\\/cr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("w"); - }); - cy.get(cesc("#\\/a\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/b\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/c\\/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("w"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/a/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/a/_answer1"].stateValues.currentResponses, - ).eqls(["u"]); - expect( - stateVariables["/a/_answer1"].stateValues - .submittedResponses, - ).eqls(["u"]); - expect(stateVariables[mathinput1Name].stateValues.value).eq( - "u", - ); - // expect(stateVariables[mathinput1Name].stateValues.submittedValue).eq('u'); - expect( - stateVariables["/b/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/b/_answer1"].stateValues.currentResponses, - ).eqls(["v"]); - expect( - stateVariables["/b/_answer1"].stateValues - .submittedResponses, - ).eqls(["v"]); - expect(stateVariables[mathinput2Name].stateValues.value).eq( - "v", - ); - // expect(stateVariables[mathinput2Name].stateValues.submittedValue).eq('v'); - expect( - stateVariables["/c/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/c/_answer1"].stateValues.currentResponses, - ).eqls(["w"]); - expect( - stateVariables["/c/_answer1"].stateValues - .submittedResponses, - ).eqls(["w"]); - expect(stateVariables[mathinput3Name].stateValues.value).eq( - "w", - ); - // expect(stateVariables[mathinput3Name].stateValues.submittedValue).eq('w'); - }); - }); - }); - - it("integrated submit buttons", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- x+y - x+z -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_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", - ); - let mathinputPartialAnchor = cesc2( - "#" + mathinputName + "_partial", - ); - - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Type correct answer in"); - cy.get(mathinputAnchor).type(`x+y`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Press enter"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Add space"); - cy.get(mathinputAnchor).type(`{end} `, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+yz'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Press enter"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Delete space"); - cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+yz'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Press enter"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Add letter"); - cy.get(mathinputAnchor).type(`{end}z`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+yz'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Delete letter (no longer goes back to saying correct)"); - cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Delete more"); - cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}`, { - force: true, - }); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Back to correct (no longer goes back to saying correct)"); - cy.get(mathinputAnchor).type(`{end}+y`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Press enter"); - cy.get(mathinputAnchor).type(`{enter}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+y'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Delete again"); - cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}`, { - force: true, - }); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(mathinputSubmitAnchor).type(`{enter}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Add letter"); - cy.get(mathinputAnchor).type(`{end}a`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'xa'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Delete letter (no longer goes back to saying incorrect)"); - cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Delete all"); - cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', ''); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log( - "Restore incorrect submitted answer (no longer goes back to saying incorrect)", - ); - cy.get(mathinputAnchor).type(`x`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(mathinputSubmitAnchor).click(); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Enter partially correct answer"); - cy.get(mathinputAnchor).type(`{end}+z`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+z'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(mathinputSubmitAnchor).click(); - // cy.get(mathinputAnchor).should('have.value', 'x+z'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("have.text", "32 %"); - - cy.log("Add letter"); - cy.get(mathinputAnchor).type(`{end}z`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+zz'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log( - "Delete letter (no longer goes back to saying partially correct)", - ); - cy.get(mathinputAnchor).type(`{end}{backspace}`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+z'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Delete more"); - cy.get(mathinputAnchor).type(`{end}{backspace}{backspace}`, { - force: true, - }); - // cy.get(mathinputAnchor).should('have.value', 'x'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log( - "Back to partial (no longer goes back to saying partially correct)", - ); - cy.get(mathinputAnchor).type(`{end}+z`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+z'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(mathinputSubmitAnchor).click(); - // cy.get(mathinputAnchor).should('have.value', 'x+z'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("have.text", "32 %"); - - cy.log("Enter invalid answer"); - cy.get(mathinputAnchor).type(`{end}/`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+z'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(mathinputSubmitAnchor).click(); - // cy.get(mathinputAnchor).should('have.value', 'x+z/'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Another invalid answer shows submit button again"); - cy.get(mathinputAnchor).type(`{end}^`, { force: true }); - // cy.get(mathinputAnchor).should('have.value', 'x+z/^'); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(mathinputSubmitAnchor).click(); - // cy.get(mathinputAnchor).should('have.value', 'x+z/^'); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - cy.get(mathinputPartialAnchor).should("not.exist"); - }); - }); - - it("integrated submit buttons, text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- hello there - bye -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - let textinputCorrectAnchor = cesc2( - "#" + textinputName + "_correct", - ); - let textinputIncorrectAnchor = cesc2( - "#" + textinputName + "_incorrect", - ); - let textinputPartialAnchor = cesc2( - "#" + textinputName + "_partial", - ); - - cy.get(textinputAnchor).should("have.value", ""); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(`hello there`); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Press enter"); - cy.get(textinputAnchor).type(`{enter}`); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(textinputSubmitAnchor).should("not.exist"); - cy.get(textinputCorrectAnchor).should("be.visible"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Add letter"); - cy.get(textinputAnchor).type(`z`); - cy.get(textinputAnchor).should("have.value", "hello therez"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Delete letter (no longer goes back to saying correct)"); - cy.get(textinputAnchor).type(`{backspace}`); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Delete more"); - cy.get(textinputAnchor).type(`{backspace}{backspace}`); - cy.get(textinputAnchor).should("have.value", "hello the"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Back to correct"); - cy.get(textinputAnchor).type(`re`); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Press enter"); - cy.get(textinputAnchor).type(`{enter}`); - cy.get(textinputAnchor).should("have.value", "hello there"); - cy.get(textinputSubmitAnchor).should("not.exist"); - cy.get(textinputCorrectAnchor).should("be.visible"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Add a space"); - cy.get(textinputAnchor).type(` `); - cy.get(textinputAnchor).should("have.value", "hello there "); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Press enter"); - cy.get(textinputAnchor).type(`{enter}`); - cy.get(textinputAnchor).should("have.value", "hello there "); - cy.get(textinputSubmitAnchor).should("not.exist"); - cy.get(textinputCorrectAnchor).should("be.visible"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Delete again"); - cy.get(textinputAnchor).type(`{backspace}{backspace}{backspace}`); - cy.get(textinputAnchor).should("have.value", "hello the"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(textinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(textinputAnchor).should("have.value", "hello the"); - cy.get(textinputSubmitAnchor).should("not.exist"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("be.visible"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Add letter"); - cy.get(textinputAnchor).type(`a`); - cy.get(textinputAnchor).should("have.value", "hello thea"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Delete letter (no longer goes back to saying incorrect)"); - cy.get(textinputAnchor).type(`{backspace}`); - cy.get(textinputAnchor).should("have.value", "hello the"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Delete all"); - cy.get(textinputAnchor).clear(); - cy.get(textinputAnchor).should("have.value", ""); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log( - "Restore incorrect submitted answer (no longer goes back to saying incorrect)", - ); - cy.get(textinputAnchor).type(`hello the`); - cy.get(textinputAnchor).should("have.value", "hello the"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Press enter"); - cy.get(textinputAnchor).type(`{enter}`); - cy.get(textinputAnchor).should("have.value", "hello the"); - cy.get(textinputSubmitAnchor).should("not.exist"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("be.visible"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Enter partially correct answer"); - cy.get(textinputAnchor).clear().type(`bye`); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(textinputSubmitAnchor).click(); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(textinputSubmitAnchor).should("not.exist"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("have.text", "32 %"); - - cy.log("Add letter"); - cy.get(textinputAnchor).type(`z`); - cy.get(textinputAnchor).should("have.value", "byez"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log( - "Delete letter (no longer goes back to saying partially correct)", - ); - cy.get(textinputAnchor).type(`{backspace}`); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Delete more"); - cy.get(textinputAnchor).type(`{backspace}{backspace}`); - cy.get(textinputAnchor).should("have.value", "b"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log( - "Back to partial (no longer goes back to saying partially correct)", - ); - cy.get(textinputAnchor).type(`ye`); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(textinputSubmitAnchor).click(); - cy.get(textinputAnchor).should("have.value", "bye"); - cy.get(textinputSubmitAnchor).should("not.exist"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(textinputPartialAnchor).should("have.text", "32 %"); - }); - }); - - it("submit buttons with two answer blanks", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter values that sum to 3x: - - $_mathinput1.immediateValue{isResponse}+$_mathinput2.immediateValue{isResponse} = 3x - $_mathinput1.immediateValue+$_mathinput2.immediateValue = 3 -

- -

$_mathinput1.immediateValue

-

$_mathinput2.immediateValue

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Enter correct answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type(`x+y`, { - force: true, - }); - cy.get(cesc("#\\/_mathinput2") + " textarea").type(`2x-y`, { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_mathinput2") + " textarea").blur(); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Type letter in input1"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}z", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Delete letter (no longer goes back to saying correct)"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}{backspace}", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Type letter in input2"); - cy.get(cesc("#\\/_mathinput1") + " textarea").blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}q", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Delete letter (no longer goes back to saying correct)"); - cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}{backspace}", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Type letter in input1"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}z", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Type letter in input2"); - cy.get(cesc("#\\/_mathinput1") + " textarea").blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}q", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Delete letter in input1"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}{backspace}", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Don't go back to saying correct if return to previous answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea").blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type("{end}{backspace}", { force: true }) - .blur(); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Enter partially correct answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`{ctrl+home}{shift+end}{backspace}x`, { force: true }) - .blur(); - cy.get(cesc("#\\/_mathinput2") + " textarea") - .type(`{ctrl+home}{shift+end}{backspace}3-x`, { force: true }) - .blur(); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.log("Delete letter in input1"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}{backspace}", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log( - "Add letter back (no longer goes back to saying partially correct)", - ); - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}x", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.log("Enter incorrect answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type(`{end}{backspace}y`, { force: true }) - .blur(); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).type("{enter}", { force: true }); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Delete letter in input2"); - cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}{backspace}", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Add letter back (no longer goes back to saying incorrect)"); - cy.get(cesc("#\\/_mathinput2") + " textarea").type("{end}x", { - force: true, - }); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).type("{enter}", { force: true }); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - }); - - it("submit buttons with two text answer blanks", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter rain and snow in either order: - - $_textinput1.immediateValue{isResponse} $_textinput2.immediateValue{isResponse} = rain snow - $_textinput1.immediateValue $_textinput2.immediateValue = snow rain - $_textinput1.immediateValue = rain - $_textinput1.immediateValue = snow - $_textinput2.immediateValue = rain - $_textinput2.immediateValue = snow -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", ""); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", ""); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Enter a correct answer"); - cy.get(cesc("#\\/_textinput1_input")).type(`rain`); - cy.get(cesc("#\\/_textinput2_input")).type(`snow`).blur(); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Type letter in input1"); - cy.get(cesc("#\\/_textinput1_input")).type("z"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rainz"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Delete letter (no longer goes back to saying correct)"); - cy.get(cesc("#\\/_textinput1_input")).type("{backspace}"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Type letter in input2"); - cy.get(cesc("#\\/_textinput1_input")).blur(); - cy.get(cesc("#\\/_textinput2_input")).type("q"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snowq"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Delete letter (no longer goes back to saying correct)"); - cy.get(cesc("#\\/_textinput2_input")).type("{backspace}"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Type letter in input1"); - cy.get(cesc("#\\/_textinput1_input")).type("z"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rainz"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Type letter in input2"); - cy.get(cesc("#\\/_textinput2_input")).type("q"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rainz"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snowq"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Delete letter in input1"); - cy.get(cesc("#\\/_textinput1_input")).type("{backspace}"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snowq"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Don't go back to saying correct if return to previous answer"); - cy.get(cesc("#\\/_textinput2_input")).type("{backspace}").blur(); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "rain"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Enter partially correct answer"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`x`).blur(); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.log("Delete letter in input2"); - cy.get(cesc("#\\/_textinput2_input")).type("{backspace}"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "sno"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log( - "Add letter back (no longer to back to saying partially correct)", - ); - cy.get(cesc("#\\/_textinput2_input")).type("w"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "snow"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.log("Enter incorrect answer"); - cy.get(cesc("#\\/_textinput2_input")).clear().type(`y`).blur(); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "y"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).type("{enter}", { force: true }); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "y"); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Delete letter in input2"); - cy.get(cesc("#\\/_textinput2_input")).type("{backspace}"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", ""); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Add letter back (no longer go back to saying incorrect"); - cy.get(cesc("#\\/_textinput2_input")).type("y"); - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "x"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "y"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).type("{enter}", { force: true }); - cy.get(cesc("#\\/_answer1_submit")).should("not.exist"); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - }); - - it("submit button with external inputs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Favorite variable:

-

Second favorite variable:

-

Enter variable: - - - $ans.immediatevalue{isResponse} = $var.immediatevalue - $ans.immediatevalue = $var2.immediatevalue - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // cy.get(cesc('#\\/var') + ' textarea').should('have.value', 'x'); - // cy.get(cesc('#\\/var2') + ' textarea').should('have.value', 'y'); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', ''); - cy.get(cesc("#\\/ans_submit")).should("be.visible"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Type correct answer in"); - cy.get(cesc("#\\/ans") + " textarea").type(`x`, { force: true }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'x'); - cy.get(cesc("#\\/ans_submit")).should("be.visible"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Press enter"); - cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'x'); - cy.get(cesc("#\\/ans_submit")).should("not.exist"); - cy.get(cesc("#\\/ans_correct")).should("be.visible"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Change correct answer"); - cy.get(cesc("#\\/var") + " textarea").type(`{end}{backspace}u{enter}`, { - force: true, - }); - // cy.get(cesc('#\\/var') + ' textarea').should('have.value', 'u'); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'x'); - cy.get(cesc("#\\/ans_submit")).should("be.visible"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Press enter"); - cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'x'); - cy.get(cesc("#\\/ans_submit")).should("not.exist"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("be.visible"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Change to new correct answer"); - cy.get(cesc("#\\/ans") + " textarea").type(`{end}{backspace}u`, { - force: true, - }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'u'); - cy.get(cesc("#\\/ans_submit")).should("be.visible"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Press enter"); - cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'u'); - cy.get(cesc("#\\/ans_submit")).should("not.exist"); - cy.get(cesc("#\\/ans_correct")).should("be.visible"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Change partial credit answer"); - cy.get(cesc("#\\/var2") + " textarea").type( - `{end}{backspace}v{enter}`, - { - force: true, - }, - ); - // cy.get(cesc('#\\/var2') + ' textarea').should('have.value', 'v'); - // cy.get(cesc('#\\/var') + ' textarea').should('have.value', 'u'); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'u'); - cy.get(cesc("#\\/ans_submit")).should("be.visible"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Press enter"); - cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'u'); - cy.get(cesc("#\\/ans_submit")).should("not.exist"); - cy.get(cesc("#\\/ans_correct")).should("be.visible"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Change to new partial correct answer"); - cy.get(cesc("#\\/ans") + " textarea").type(`{end}{backspace}v`, { - force: true, - }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'v'); - cy.get(cesc("#\\/ans_submit")).should("be.visible"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Press enter"); - cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'v'); - cy.get(cesc("#\\/ans_submit")).should("not.exist"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("be.visible"); - - cy.log("Change correct answer"); - cy.get(cesc("#\\/var") + " textarea").type(`{end}{backspace}w{enter}`, { - force: true, - }); - // cy.get(cesc('#\\/var') + ' textarea').should('have.value', 'w'); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'v'); - // cy.get(cesc('#\\/var2') + ' textarea').should('have.value', 'v'); - cy.get(cesc("#\\/ans_submit")).should("be.visible"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Press enter"); - cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'v'); - cy.get(cesc("#\\/ans_submit")).should("not.exist"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("be.visible"); - - cy.log("Change to new correct answer"); - cy.get(cesc("#\\/ans") + " textarea").type(`{end}{backspace}w`, { - force: true, - }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'w'); - cy.get(cesc("#\\/ans_submit")).should("be.visible"); - cy.get(cesc("#\\/ans_correct")).should("not.exist"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - - cy.log("Press enter"); - cy.get(cesc("#\\/ans") + " textarea").type(`{enter}`, { force: true }); - // cy.get(cesc('#\\/ans') + ' textarea').should('have.value', 'w'); - cy.get(cesc("#\\/ans_submit")).should("not.exist"); - cy.get(cesc("#\\/ans_correct")).should("be.visible"); - cy.get(cesc("#\\/ans_incorrect")).should("not.exist"); - cy.get(cesc("#\\/ans_partial")).should("not.exist"); - }); - - it("answer with shuffled inline choiceinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - - cat - dog - monkey - - .

-

Current response: $_answer1.currentResponse

-

Submitted response: $_answer1.submittedResponse

-

Credit for submitted response: $_answer1.creditAchieved

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", ""); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = {}; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - "/_choiceinput1" - ].stateValues.choiceTexts.entries()) { - indexByName[val] = ind + 1; - } - - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`dog`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`monkey`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`cat`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Select incorrect answer again"); - cy.get(cesc("#\\/_choiceinput1")).select(`monkey`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Does not remember previously submitted answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`cat`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - }); - - it("answer inline, shuffled with sugared choices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - cat - dog - monkey - .

-

Current response: $_answer1.currentResponse

-

Submitted response: $_answer1.submittedResponse

-

Credit for submitted response: $_answer1.creditAchieved

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let choiceinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let choiceinputAnchor = cesc2("#" + choiceinputName); - let choiceinputSubmitAnchor = cesc2( - "#" + choiceinputName + "_submit", - ); - let choiceinputCorrectAnchor = cesc2( - "#" + choiceinputName + "_correct", - ); - let choiceinputIncorrectAnchor = cesc2( - "#" + choiceinputName + "_incorrect", - ); - let choiceinputPartialAnchor = cesc2( - "#" + choiceinputName + "_partial", - ); - - cy.get(choiceinputAnchor).should("have.value", ""); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", ""); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = {}; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - choiceinputName - ].stateValues.choiceTexts.entries()) { - indexByName[val] = ind + 1; - } - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select correct answer"); - cy.get(choiceinputAnchor).select(`dog`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("be.visible"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(choiceinputAnchor).select(`monkey`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("be.visible"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select partially correct answer"); - cy.get(choiceinputAnchor).select(`cat`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Select incorrect answer again"); - cy.get(choiceinputAnchor).select(`monkey`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Does not remember previously submitted answer"); - cy.get(choiceinputAnchor).select(`cat`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Submit answer"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - }); - }); - - it("answer with inline choiceinput, specify component type for submitted", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - - cat - dog - monkey - - .

-

Current response: $_answer1.currentResponse

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", ""); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = {}; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - "/_choiceinput1" - ].stateValues.choiceTexts.entries()) { - indexByName[val] = ind + 1; - } - - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`dog`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`monkey`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`cat`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Select incorrect answer again"); - cy.get(cesc("#\\/_choiceinput1")).select(`monkey`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Does not remember previously submitted answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`cat`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - }); - - it("answer with inline choiceinput, fixedorder", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - - cat - dog - monkey - - .

-

Current response: $_answer1.currentResponse

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/_choiceinput1")).should("have.text", "catdogmonkey"); - - cy.get(cesc("#\\/cr")).should("have.text", ""); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - "/_choiceinput1" - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`dog`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`monkey`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`cat`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`monkey`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Does not remember previously submitted answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`cat`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - }); - - it("answer inline, fixedorder with sugared choices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - cat - dog - monkey - .

-

Current response: $_answer1.currentResponse

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let choiceinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let choiceinputAnchor = cesc2("#" + choiceinputName); - let choiceinputSubmitAnchor = cesc2( - "#" + choiceinputName + "_submit", - ); - let choiceinputCorrectAnchor = cesc2( - "#" + choiceinputName + "_correct", - ); - let choiceinputIncorrectAnchor = cesc2( - "#" + choiceinputName + "_incorrect", - ); - let choiceinputPartialAnchor = cesc2( - "#" + choiceinputName + "_partial", - ); - - cy.get(choiceinputAnchor).should("have.value", ""); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(choiceinputAnchor).should("have.text", "catdogmonkey"); - - cy.get(cesc("#\\/cr")).should("have.text", ""); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - choiceinputName - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select correct answer"); - cy.get(choiceinputAnchor).select(`dog`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("be.visible"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(choiceinputAnchor).select(`monkey`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("be.visible"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select partially correct answer"); - cy.get(choiceinputAnchor).select(`cat`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(choiceinputAnchor).select(`monkey`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Does not remember previously submitted answer"); - cy.get(choiceinputAnchor).select(`cat`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Submit answer"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - }); - }); - - it("answer with select-multiple inline choiceinput, fixedorder", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - - cat - dog - monkey - - .

-

Current response: $_answer1.currentResponses

-

Submitted response: $_answer1.submittedResponses

-

Credit for submitted response: $_answer1.creditAchieved{name="credit"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1")) - .invoke("val") - .should("deep.equal", []); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/_choiceinput1")).should("have.text", "catdogmonkey"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: "); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - "/_choiceinput1" - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select half of correct answer"); - cy.get(cesc("#\\/_choiceinput1")).select([`dog`]); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: dog"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select both correct answers"); - cy.get(cesc("#\\/_choiceinput1")).select(["dog", "cat"]); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: dog"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")).select(`monkey`); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: monkey"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: monkey"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select all answers"); - cy.get(cesc("#\\/_choiceinput1")).select([`monkey`, `cat`, `dog`]); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "67 %"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 2 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Select partially correct and incorrect answers"); - cy.get(cesc("#\\/_choiceinput1")).select([`monkey`, , `dog`]); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 2 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("have.text", "33 %"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.333"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - }); - - it("answer select-multiple, inline, fixedorder with sugared choices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - cat - dog - monkey - .

-

Current response: $_answer1.currentResponses

-

Submitted response: $_answer1.submittedResponses

-

Credit for submitted response: $_answer1.creditAchieved{name="credit"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let choiceinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let choiceinputAnchor = cesc2("#" + choiceinputName); - let choiceinputSubmitAnchor = cesc2( - "#" + choiceinputName + "_submit", - ); - let choiceinputCorrectAnchor = cesc2( - "#" + choiceinputName + "_correct", - ); - let choiceinputIncorrectAnchor = cesc2( - "#" + choiceinputName + "_incorrect", - ); - let choiceinputPartialAnchor = cesc2( - "#" + choiceinputName + "_partial", - ); - - cy.get(choiceinputAnchor).invoke("val").should("deep.equal", []); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(choiceinputAnchor).should("have.text", "catdogmonkey"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: "); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - choiceinputName - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select half of correct answer"); - cy.get(choiceinputAnchor).select([`dog`]); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select both correct answers"); - cy.get(choiceinputAnchor).select(["dog", "cat"]); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("be.visible"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(choiceinputAnchor).select(`monkey`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("be.visible"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select all answers"); - cy.get(choiceinputAnchor).select([`monkey`, `cat`, `dog`]); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "67 %"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(2 / 3); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Select partially correct and incorrect answers"); - cy.get(choiceinputAnchor).select([`monkey`, , `dog`]); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(2 / 3); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "33 %"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.333"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1 / 3); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - }); - }); - - it("answer with block choiceinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a:

- - - cat - dog - monkey - - -

Current response: $_answer1.currentResponse

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", ""); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = {}; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - "/_choiceinput1" - ].stateValues.choiceTexts.entries()) { - indexByName[val] = ind + 1; - } - - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`monkey`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Select incorrect answer again"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`monkey`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Does not remember previously submitted answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - }); - - it("answer block, shuffled, with sugared choices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a:

- - cat - dog - monkey - -

Current response: $_answer1.currentResponse

-

Submitted response:

-

Credit for submitted response: $_answer1.creditAchieved

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let choiceinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let choiceinputAnchor = cesc2("#" + choiceinputName); - let choiceinputSubmitAnchor = cesc2( - "#" + choiceinputName + "_submit", - ); - let choiceinputCorrectAnchor = cesc2( - "#" + choiceinputName + "_correct", - ); - let choiceinputIncorrectAnchor = cesc2( - "#" + choiceinputName + "_incorrect", - ); - let choiceinputPartialAnchor = cesc2( - "#" + choiceinputName + "_partial", - ); - - cy.get(choiceinputAnchor).should("have.value", ""); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", ""); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = {}; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - choiceinputName - ].stateValues.choiceTexts.entries()) { - indexByName[val] = ind + 1; - } - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select correct answer"); - cy.get(choiceinputAnchor).contains(`dog`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", ""); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "dog"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(choiceinputAnchor).contains(`monkey`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "dog"); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select partially correct answer"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "monkey"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Select incorrect answer again"); - cy.get(choiceinputAnchor).contains(`monkey`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "monkey"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Does not remember previously submitted answer"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - - cy.log("Submit answer"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.get(cesc("#\\/cr")).should("have.text", "cat"); - cy.get(cesc("#\\/sr")).should("have.text", "cat"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"]]); - }); - }); - }); - - it("answer with select-multiple block choiceinput, fixedorder", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - - cat - dog - monkey - - .

-

Current response: $_answer1.currentResponses

-

Submitted response: $_answer1.submittedResponses

-

Credit for submitted response: $_answer1.creditAchieved{name="credit"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: "); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - "/_choiceinput1" - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select half of correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: dog"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select both correct answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: dog"); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`monkey`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: monkey"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: monkey"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select all answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Select partially correct and incorrect answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - }); - - it("answer select-multiple, block, fixedorder with sugared choices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - cat - dog - monkey - .

-

Current response: $_answer1.currentResponses

-

Submitted response: $_answer1.submittedResponses

-

Credit for submitted response: $_answer1.creditAchieved{name="credit"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let choiceinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let choiceinputAnchor = cesc2("#" + choiceinputName); - let choiceinputSubmitAnchor = cesc2( - "#" + choiceinputName + "_submit", - ); - let choiceinputCorrectAnchor = cesc2( - "#" + choiceinputName + "_correct", - ); - let choiceinputIncorrectAnchor = cesc2( - "#" + choiceinputName + "_incorrect", - ); - let choiceinputPartialAnchor = cesc2( - "#" + choiceinputName + "_partial", - ); - - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: "); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - choiceinputName - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select half of correct answer"); - cy.get(choiceinputAnchor).contains(`dog`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("be.visible"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select both correct answers"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("be.visible"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputAnchor).contains(`dog`).click({ force: true }); - cy.get(choiceinputAnchor).contains(`monkey`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("be.visible"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select all answers"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputAnchor).contains(`dog`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("be.visible"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Select partially correct and incorrect answers"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("be.visible"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - }); - }); - - it("answer with select-multiple block choiceinput, fixedorder, match partial", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - - cat - dog - monkey - - .

-

Current response: $_answer1.currentResponses

-

Submitted response: $_answer1.submittedResponses

-

Credit for submitted response: $_answer1.creditAchieved{name="credit"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: "); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - "/_choiceinput1" - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select half of correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should( - "have.text", - "50% Correct", - ); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: dog"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select both correct answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: dog"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`monkey`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: monkey"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: monkey"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select all answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should( - "have.text", - "67% Correct", - ); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 2 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Select partially correct and incorrect answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 2 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should( - "have.text", - "33% Correct", - ); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.333"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - }); - - it("answer select-multiple, block, fixedorder, match partial, with sugared choices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - cat - dog - monkey - .

-

Current response: $_answer1.currentResponses

-

Submitted response: $_answer1.submittedResponses

-

Credit for submitted response: $_answer1.creditAchieved{name="credit"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let choiceinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let choiceinputAnchor = cesc2("#" + choiceinputName); - let choiceinputSubmitAnchor = cesc2( - "#" + choiceinputName + "_submit", - ); - let choiceinputCorrectAnchor = cesc2( - "#" + choiceinputName + "_correct", - ); - let choiceinputIncorrectAnchor = cesc2( - "#" + choiceinputName + "_incorrect", - ); - let choiceinputPartialAnchor = cesc2( - "#" + choiceinputName + "_partial", - ); - - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: "); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - choiceinputName - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select half of correct answer"); - cy.get(choiceinputAnchor).contains(`dog`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "50% Correct"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select both correct answers"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0.5); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("be.visible"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputAnchor).contains(`dog`).click({ force: true }); - cy.get(choiceinputAnchor).contains(`monkey`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("be.visible"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select all answers"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputAnchor).contains(`dog`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(0); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "67% Correct"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(2 / 3); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Select partially correct and incorrect answers"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(2 / 3); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "33% Correct"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.333"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1 / 3); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables[choiceinputName].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - }); - }); - - it("answer with select-multiple block choiceinput, fixedorder, match partial in answer", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a - - cat - dog - monkey - - .

-

Current response: $_answer1.currentResponses

-

Submitted response: $_answer1.submittedResponses

-

Credit for submitted response: $_answer1.creditAchieved{name="credit"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: "); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - let indexByName = { cat: 1, dog: 2, monkey: 3 }; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let [ind, val] of stateVariables[ - "/_choiceinput1" - ].stateValues.choiceTexts.entries()) { - expect(indexByName[val]).eq(ind + 1); - } - - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls([]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([]); - }); - - cy.log("Select half of correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: "); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls([]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should( - "have.text", - "50% Correct", - ); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: dog"); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: dog"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"]]); - }); - - cy.log("Select both correct answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should("have.text", "Submitted response: dog"); - cy.get(cesc("#\\/credit")).should("have.text", "0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0.5, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["cat"], indexByName["dog"]]); - }); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`monkey`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: monkey"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog", - ); - cy.get(cesc("#\\/credit")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should("have.text", "Current response: monkey"); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["monkey"]]); - }); - - cy.log("Select all answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 0, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should( - "have.text", - "67% Correct", - ); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: cat, dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 2 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([ - indexByName["cat"], - indexByName["dog"], - indexByName["monkey"], - ]); - }); - - cy.log("Select partially correct and incorrect answers"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`cat`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("be.visible"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: cat, dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.667"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 2 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["cat", "dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should( - "have.text", - "33% Correct", - ); - - cy.get(cesc("#\\/cr")).should( - "have.text", - "Current response: dog, monkey", - ); - cy.get(cesc("#\\/sr")).should( - "have.text", - "Submitted response: dog, monkey", - ); - cy.get(cesc("#\\/credit")).should("have.text", "0.333"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.creditAchieved).eq( - 1 / 3, - ); - expect( - stateVariables["/_answer1"].stateValues.currentResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_answer1"].stateValues.submittedResponses, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedValues, - ).eqls(["dog", "monkey"]); - expect( - stateVariables["/_choiceinput1"].stateValues.selectedIndices, - ).eqls([indexByName["dog"], indexByName["monkey"]]); - }); - }); - - it("answer with choiceinput, no bug when submit first", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

The animal is a:

- - - cat - dog - monkey - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`dog`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - }); - - it("answer with variable number of choices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Num:

- - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_choiceinput1"].stateValues.choiceTexts.length, - ).eq(3); - }); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 1`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`plus a bit is 0.001`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 0.5`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.log("add another choice"); - cy.get(cesc("#\\/num") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_choiceinput1") + " label:nth-of-type(4)").should( - "be.visible", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_choiceinput1"].stateValues.choiceTexts.length, - ).eq(4); - }); - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 1`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`plus a bit is 0.001`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 0.333`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("33% correct"); - }); - - cy.log("Select another partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 0.667`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("67% correct"); - }); - - cy.log("go back to 3 choices"); - cy.get(cesc("#\\/num") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_choiceinput1") + " label:nth-of-type(4)").should( - "not.exist", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_choiceinput1"].stateValues.choiceTexts.length, - ).eq(3); - }); - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 1`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`plus a bit is 0.001`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 0.5`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.log("create 6 choices"); - cy.get(cesc("#\\/num") + " textarea").type("{end}{backspace}6{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_choiceinput1") + " label:nth-of-type(6)").should( - "be.visible", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_choiceinput1"].stateValues.choiceTexts.length, - ).eq(6); - }); - - cy.get(cesc("#\\/_choiceinput1")).should("have.value", ""); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 1`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Click submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select incorrect answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`plus a bit is 0.001`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Select partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 0.2`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("20% correct"); - }); - - cy.log("Select another partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 0.4`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - - cy.log("Select another partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 0.6`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("60% correct"); - }); - - cy.log("Select another partially correct answer"); - cy.get(cesc("#\\/_choiceinput1")) - .contains(`Get 0.8`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(cesc("#\\/_choiceinput1_submit")).type(`{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_correct")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_choiceinput1_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("80% correct"); - }); - }); - - it("answer with user-defined choice and credit", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Credit for cat:

-

Last option:

- - - cat - dog - monkey - $last.value - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let choiceinputName = cesc2( - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName, - ); - let choiceinputAnchor = "#" + choiceinputName; - let choiceinputSubmitAnchor = "#" + choiceinputName + "_submit"; - let choiceinputCorrectAnchor = "#" + choiceinputName + "_correct"; - let choiceinputIncorrectAnchor = - "#" + choiceinputName + "_incorrect"; - let choiceinputPartialAnchor = "#" + choiceinputName + "_partial"; - - cy.get(choiceinputAnchor).should("have.value", ""); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Select correct answer"); - cy.get(choiceinputAnchor).contains(`dog`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Change partial credit for cat"); - cy.get(cesc("#\\/catcredit") + " textarea").type( - "{end}{backspace}4{enter}", - { force: true }, - ); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Change last choice"); - cy.get(cesc("#\\/last_input")).clear().type("mouse{enter}"); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Select partially correct answer"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - - cy.log("Change partial credit for cat"); - cy.get(cesc("#\\/catcredit") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("20% correct"); - }); - - cy.log("Select variable answer"); - cy.get(choiceinputAnchor).contains(`mouse`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(choiceinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Change animal name"); - cy.get(cesc("#\\/last_input")).clear().type("rabbit{enter}"); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - cy.get(choiceinputPartialAnchor).should("not.exist"); - }); - }); - - it("switch answer between inline and block", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Inline:

- - - cat - dog - monkey - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let choiceinputName = cesc2( - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName, - ); - let choiceinputAnchor = "#" + choiceinputName; - let choiceinputSubmitAnchor = "#" + choiceinputName + "_submit"; - let choiceinputCorrectAnchor = "#" + choiceinputName + "_correct"; - let choiceinputIncorrectAnchor = - "#" + choiceinputName + "_incorrect"; - let choiceinputPartialAnchor = "#" + choiceinputName + "_partial"; - - cy.get(choiceinputAnchor).should("have.value", ""); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("toggle inline"); - cy.get(cesc("#\\/inline")).click(); - cy.get(`${choiceinputAnchor} option:nth-of-type(3)`).should( - "be.visible", - ); - cy.get(choiceinputAnchor).should("have.value", ""); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Select correct answer"); - cy.get(choiceinputAnchor).select(`dog`); - cy.get(choiceinputSubmitAnchor).should("be.visible"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("be.visible"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("toggle inline"); - cy.get(cesc("#\\/inline")).click(); - cy.get(`${choiceinputAnchor} label:nth-of-type(3)`).should( - "be.visible", - ); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Select partial credit answer"); - cy.get(choiceinputAnchor).contains(`cat`).click({ force: true }); - cy.get(choiceinputSubmitAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("not.exist"); - - cy.log("Click submit button"); - cy.get(choiceinputSubmitAnchor).click(); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("50% correct"); - }); - - cy.log("toggle inline"); - cy.get(cesc("#\\/inline")).click(); - cy.get(`${choiceinputAnchor} option:nth-of-type(3)`).should( - "be.visible", - ); - cy.get(choiceinputSubmitAnchor).should("not.exist"); - cy.get(choiceinputCorrectAnchor).should("not.exist"); - cy.get(choiceinputIncorrectAnchor).should("not.exist"); - cy.get(choiceinputPartialAnchor).should("have.text", "50 %"); - }); - }); - - it("answer, any letter", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter any letter: - - - - $userx_input.immediatevalue elementof {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z} - - - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // cy.get(cesc('#\\/userx_input_input')).should('have.value', ''); - cy.get(cesc("#\\/userx_input_submit")).should("be.visible"); - - cy.log("Enter a letter"); - cy.get(cesc("#\\/userx_input") + " textarea").type("a{enter}", { - force: true, - }); - cy.get(cesc("#\\/userx_input_correct")).should("be.visible"); - - cy.log("Enter letter combination"); - cy.get(cesc("#\\/userx_input") + " textarea").type( - "{end}{backspace}c,d", - { - force: true, - }, - ); - cy.get(cesc("#\\/userx_input_submit")).click(); - cy.get(cesc("#\\/userx_input_incorrect")).should("be.visible"); - - cy.log("Enter another letter"); - cy.get(cesc("#\\/userx_input") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}q", - { force: true }, - ); - cy.get(cesc("#\\/userx_input_submit")).click(); - cy.get(cesc("#\\/userx_input_correct")).should("be.visible"); - - cy.log("Enter a number"); - cy.get(cesc("#\\/userx_input") + " textarea").type( - "{end}{backspace}1", - { - force: true, - }, - ); - cy.get(cesc("#\\/userx_input_submit")).click(); - cy.get(cesc("#\\/userx_input_incorrect")).should("be.visible"); - }); - - it("answer element of user defined set", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

Enter a set

-

Enter an element of that set: - - - - $element.immediatevalue elementof $set.value - - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // cy.get(cesc('#\\/element_input')).should('have.value', ''); - // cy.get(cesc('#\\/set_input')).should('have.value', '{ 1, 2, 3 }'); - cy.get(cesc("#\\/element_submit")).should("be.visible"); - - cy.log("Enter a number from set"); - cy.get(cesc("#\\/element") + " textarea").type("2{enter}", { - force: true, - }); - cy.get(cesc("#\\/element_correct")).should("be.visible"); - - cy.log("Enter all numbers from set"); - cy.get(cesc("#\\/element") + " textarea").type( - "{end}{backspace}1,2,3", - { - force: true, - }, - ); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_incorrect")).should("be.visible"); - - cy.log("Enter a letter"); - cy.get(cesc("#\\/element") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}c", - { force: true }, - ); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_incorrect")).should("be.visible"); - - cy.log("Change set to letters"); - cy.get(cesc("#\\/set") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}{{}a,b,c,d,e,f,g", - { force: true }, - ); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_correct")).should("be.visible"); - - cy.log("Enter another letter"); - cy.get(cesc("#\\/element") + " textarea").type("{end}{backspace}g", { - force: true, - }); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_correct")).should("be.visible"); - - cy.log("Enter a number"); - cy.get(cesc("#\\/element") + " textarea").type("{end}{backspace}2", { - force: true, - }); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_incorrect")).should("be.visible"); - - cy.log("Change set to mathematical expressions"); - cy.get(cesc("#\\/set") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}{{}(x+y)/2{rightarrow}, e^(x^2{rightarrow} + y){rightArrow}, (1,2,3)", - { force: true }, - ); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_incorrect")).should("be.visible"); - - cy.log("Enter one of the expressions"); - cy.get(cesc("#\\/element") + " textarea").type( - "{end}{backspace}(1,2,3)", - { - force: true, - }, - ); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_correct")).should("be.visible"); - - cy.log("Enter another of the expressions"); - cy.get(cesc("#\\/element") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}e^(x^2{rightarrow} + y)", - { force: true }, - ); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_correct")).should("be.visible"); - - cy.log("Enter third expression"); - cy.get(cesc("#\\/element") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}x+2y-x/2{rightarrow}-3y/2", - { force: true }, - ); - cy.get(cesc("#\\/element_submit")).click(); - cy.get(cesc("#\\/element_correct")).should("be.visible"); - }); - - it("answer based on math and text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter a number larger than one

-

Say hello:

- - - - $_mathinput1.immediateValue{isResponse} > 1 - and - $_textinput1.immediateValue{isResponse} = hello - - - -

Your current math answer is

-

Your current text answer is

-

Your submitted math answer is

-

Your submitted text answer is

-

Credit for your answers $a.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", ""); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("2{enter}", { - force: true, - }); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "2"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", ""); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "2"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", ""); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.get(cesc("#\\/_textinput1_input")).clear().type(`hello{enter}`); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(cesc(`#\\/sr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "0"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "0"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - }); - - it("answer based on math and text, match partial in answer", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter a number larger than one

-

Say hello:

- - - - $_mathinput1 > 1 - and - $_textinput1 = hello - - - -

Your current math answer is

-

Your current text answer is

-

Your submitted math answer is

-

Your submitted text answer is

-

Credit for your answers $a.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", ""); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("2{enter}", { - force: true, - }); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "2"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", ""); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "2"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", ""); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.get(cesc("#\\/_textinput1_input")).clear().type(`hello{enter}`); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", ""); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(cesc(`#\\/sr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "0"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "0"); - - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/cr2`)).should("have.text", "hello"); - - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/sr2`)).should("have.text", "hello"); - cy.get(cesc(`#\\/ca`)).should("have.text", "0.5"); - }); - - it("answer with submitted response based on point", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Criterion:

-

Move point so that its x-coordinate is larger than $_mathinput1.value.

- - - (0,0) - - - - - $_mathinput1.immediateValue < $_point1.x{isResponse} - - - -

Your current answer:

-

Your submitted answer:

-

Credit for your answer $a.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "0"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 3, y: -3 }, - }); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "3"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "3"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}4{enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "3"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: 9 }, - }); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "8"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("8"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "8"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("8"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("8"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - }); - }); - - it("answer with unicode", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+2pi+3gamma+4mu+5xi+6eta

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_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.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - - cy.log("Symbols as escaped text"); - cy.get(mathinputAnchor).type( - `x+2\\pi+3\\gamma+4\\mu+5\\xi+6\\eta{enter}{enter}`, - { force: true }, - ); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - - cy.log("Incorrect answer"); - cy.get(mathinputAnchor).type(`{ctrl+home}{shift+end}{backspace}x`, { - force: true, - }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.log("Symbols as unicode"); - cy.get(mathinputAnchor).type(`{end}{backspace}x+2Ο€+3Ξ³+4ΞΌ+5ΞΎ+6Ξ·`, { - force: true, - }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - }); - }); - - it("mark targets as responses", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter minimum:

-

Enter value larger than $min:

- - - $val > $min - - -

Current response

-

Submitted response

-

Credit: $a.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.numResponses).eq(1); - }); - - cy.get(cesc("#\\/min") + " textarea").type("2{enter}", { force: true }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/val") + " textarea").type("3{enter}", { force: true }); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "3"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/sr`) + ` .mjx-mrow`).should("have.text", "3"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - }); - - it("consider as responses", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter two 2D points, where second to upward and to the right of the first: -

- - - - - - - - $P $Q - $(QQ.x) > $(PP.x) and $(QQ.y) > $(PP.y) - - -

Current responses $a.currentResponses{assignNames="cr1 cr2" createComponentOfType="math" numComponents="2"}

-

Submitted responses $a.submittedResponses{assignNames="sr1 sr2" createComponentOfType="math" numComponents="2"}

-

Credit: $a.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.numResponses).eq(2); - }); - - cy.get(cesc("#\\/P") + " textarea").type("(2,3){enter}", { - force: true, - }); - cy.get(cesc("#\\/Q") + " textarea").type("(3,4){enter}", { - force: true, - }); - - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("contain.text", "(2,3)"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("contain.text", "(3,4)"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,3)"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("contain.text", "(2,3)"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("contain.text", "(3,4)"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,3)"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,3)"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.get(cesc("#\\/P") + " textarea").type( - "{home}{rightArrow}{rightArrow}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/Q") + " textarea").type( - "{end}{leftArrow}{backspace}1{enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("contain.text", "(5,3)"); - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("contain.text", "(3,1)"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,3)"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,3)"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("contain.text", "(5,3)"); - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("contain.text", "(3,1)"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,3)"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,3)"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - }); - - it("isResponse is not copied", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - $mi{isResponse name="v"} = x - - - $v = y - - - $v = z - - -

-

Submitted responses of ans: $ans.submittedResponses{assignNames="sr1 sr2 sr3"}

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mi") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_correct")).should("be.visible"); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("90% correct"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("80% correct"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - }); - - it("isResponse from sourcesAreResponses is not copied", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a1: - - - $mi{name="v"} = x - - - $v = y - - - $v = z - - -

-

Submitted responses of ans: $ans.submittedResponses{assignNames="sr1 sr2 sr3"}

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mi") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_correct")).should("be.visible"); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("90% correct"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("80% correct"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - }); - - it("isResponse from sourcesAreResponses is not recursively copied", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a1: - - - $mi = x - - - $m = y - - - $m.value = z - - -

-

Submitted responses of ans: $ans.submittedResponses{assignNames="sr1 sr2 sr3"}

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mi") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_correct")).should("be.visible"); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("90% correct"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/ans_submit")).click(); - cy.get(cesc("#\\/ans_partial")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("80% correct"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/sr2")).should("not.exist"); - cy.get(cesc("#\\/sr3")).should("not.exist"); - }); - - it("all composites are responses if no responses indicated", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter minimum:

-

Enter value larger than $min:

- - - $val > $min - - -

Current responses $a.currentResponses{assignNames="cr1 cr2" createComponentOfType="math" numComponents="2"}

-

Submitted response $a.submittedResponses{assignNames="sr1 sr2" createComponentOfType="math" numComponents="2"}

-

Credit: $a.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.numResponses).eq(2); - }); - - cy.get(cesc("#\\/min") + " textarea").type("2{enter}", { force: true }); - - cy.get(cesc(`#\\/cr2`) + ` .mjx-mrow`).should("have.text", "2"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/sr2`) + ` .mjx-mrow`).should("have.text", "2"); - - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/val") + " textarea").type("3{enter}", { force: true }); - - cy.get(cesc(`#\\/cr1`) + ` .mjx-mrow`).should("have.text", "3"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(cesc(`#\\/sr1`) + ` .mjx-mrow`).should("have.text", "3"); - cy.get(cesc(`#\\/cr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/cr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/sr1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - }); - - it("immediate value used for submit button", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter value larger than 3:

- - - $val > 3 - - -

Current response:

-

Submitted response:

-

Credit: $a.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let submitAnchor = cesc2("#/a_submit"); - let correctAnchor = cesc2("#/a_correct"); - let incorrectAnchor = cesc2("#/a_incorrect"); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/val") + " textarea").type("3{enter}", { force: true }); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("contain.text", "3"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}4", { - force: true, - }); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}3", { - force: true, - }); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}5", { - force: true, - }); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/val") + " textarea").blur(); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "5"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("be.visible"); - cy.get(incorrectAnchor).should("not.exist"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc(`#\\/ca`)).should("have.text", "1"); - }); - - it("choiceinput credit from boolean", () => { - let options = ["meow", "woof", "squeak", "blub"]; - for (let ind = 1; ind <= 4; ind++) { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - ${ind} - - - - -

What does the $animal say? - - - meow - woof - squeak - blub - - -

- `, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", `${ind}`); // to wait until loaded - - for (let ind2 = 1; ind2 <= 4; ind2++) { - cy.get(cesc("#\\/_choiceinput1")) - .contains(options[ind2 - 1]) - .click({ force: true }); - - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_submit")).should("not.exist"); - if (ind2 === ind) { - cy.get(cesc("#\\/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should( - "not.exist", - ); - } else { - cy.get(cesc("#\\/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should( - "be.visible", - ); - } - } - } - }); - - it("award credit from boolean", () => { - let options = ["meow", "woof", "squeak", "blub"]; - for (let ind = 1; ind <= 4; ind++) { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - ${ind} - - - - -

What does the $animal say? - - meow - woof - squeak - blub - -

- `, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", `${ind}`); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let textinputName = - stateVariables["/ans"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2( - "#" + textinputName + "_submit", - ); - let textinputCorrectAnchor = cesc2( - "#" + textinputName + "_correct", - ); - let textinputIncorrectAnchor = cesc2( - "#" + textinputName + "_incorrect", - ); - - for (let ind2 = 1; ind2 <= 4; ind2++) { - cy.get(textinputAnchor) - .clear() - .type(options[ind2 - 1]); - cy.get(textinputSubmitAnchor).click(); - - cy.get(textinputSubmitAnchor).should("not.exist"); - if (ind2 === ind) { - cy.get(textinputCorrectAnchor).should("be.visible"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - } else { - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("be.visible"); - } - } - }); - } - }); - - it("number of awards credited", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number of awards credited:

-

Credit for combined award:

-

Distinct numbers greater than 3: - - - - $mi1 > 3 - $mi2 > 3 - $mi1 > 3 and $mi2 > 3 and $mi1 != $mi2 - $mi1 - isnumber($mi2) - -

- -
- $a.feedbacks{assignNames="fb1 fb2 fb3 fb4 fb5"} -
- -

Current responses: $a.currentResponses{assignNames="cr1 cr2" createComponentOfType="math" numComponents="2"}

-

Submitted response: $a.submittedResponses{assignNames="sr1 sr2" createComponentOfType="math" numComponents="2"}

-

Credit: $a.creditAchieved{assignNames="ca"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let submitAnchor = cesc2("#/a_submit"); - let correctAnchor = cesc2("#/a_correct"); - let incorrectAnchor = cesc2("#/a_incorrect"); - let partialAnchor = cesc2("#/a_partial"); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should("not.exist"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should("not.exist"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi2") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "At least the second is a number", - ); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi1") + " textarea").type("0{enter}", { force: true }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "At least the first is a number", - ); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/nawards") + " textarea").type( - "{end}{backspace}3{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "At least the first is a number", - ); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "At least the second is a number", - ); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - // make sure don't have a comma displayed between feedbacks - cy.get(cesc("#\\/theFeedbacks")).should( - "contain.text", - "At least the first is a number", - ); - cy.get(cesc("#\\/theFeedbacks")).should( - "contain.text", - "At least the second is a number", - ); - cy.get(cesc("#\\/theFeedbacks")).should("not.contain.text", ","); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi1") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is greater than 3"); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "At least the first is a number", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "At least the second is a number", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0.4"); - - cy.get(cesc("#\\/nawards") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is greater than 3"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0.4"); - - cy.get(cesc("#\\/mi2") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is greater than 3"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0.4"); - - cy.get(cesc("#\\/nawards") + " textarea").type( - "{end}{backspace}3{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("80% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is greater than 3"); - cy.get(cesc("#\\/fb2")).should("have.text", "Second is greater than 3"); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "At least the first is a number", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0.8"); - - cy.get(cesc("#\\/mi2") + " textarea").type("{end}{backspace}5{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("be.visible"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is greater than 3"); - cy.get(cesc("#\\/fb2")).should("have.text", "Second is greater than 3"); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Distinct and greater than 3", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - - cy.get(cesc("#\\/nawards") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("be.visible"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "Distinct and greater than 3", - ); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - - cy.get(cesc("#\\/creditForCombined") + " textarea").type( - "{end}{backspace}0.2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is greater than 3"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0.4"); - - cy.get(cesc("#\\/nawards") + " textarea").type( - "{end}{backspace}2{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("80% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is greater than 3"); - cy.get(cesc("#\\/fb2")).should("have.text", "Second is greater than 3"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0.8"); - - cy.get(cesc("#\\/nawards") + " textarea").type( - "{end}{backspace}3{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("be.visible"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is greater than 3"); - cy.get(cesc("#\\/fb2")).should("have.text", "Second is greater than 3"); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Distinct and greater than 3", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/cr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/cr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - }); - - it("number of awards credited 2", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - - $mi1 > 0 - $mi2 > 0 - $mi3 > 0 - $mi1 > $mi2 - $mi1 > $mi3 - $mi2 > $mi3 - $mi1 + $mi2 > 5 - $mi1 + $mi3 > 5 - $mi2 + $mi3 > 5 - $mi1 - not isnumber($mi2) - isnumber($mi3) - -

- - $a.feedbacks{assignNames="fb1 fb2 fb3 fb4 fb5"} - -

Credit: $a.creditAchieved{assignNames="ca"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let submitAnchor = cesc2("#/a_submit"); - let correctAnchor = cesc2("#/a_correct"); - let incorrectAnchor = cesc2("#/a_incorrect"); - let partialAnchor = cesc2("#/a_partial"); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should("not.exist"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "The first should be a number", - ); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "The second should be a number", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "The third should be a number", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi1") + " textarea").type("-5{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "The second should be a number", - ); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "The third should be a number", - ); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi2") + " textarea").type("-5{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "The third should be a number", - ); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi3") + " textarea").type("-5{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should("not.exist"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi2") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("10% correct"); - }); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "Second is larger than third", - ); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.1"); - - cy.get(cesc("#\\/mi1") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("20% correct"); - }); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "First is larger than third", - ); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "Second is larger than third", - ); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.2"); - - cy.get(cesc("#\\/mi1") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("30% correct"); - }); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "First is larger than second", - ); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "First is larger than third", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Second is larger than third", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.3"); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{end}{backspace}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("40% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is positive"); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "First is larger than second", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "First is larger than third", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.4"); - - cy.get(cesc("#\\/mi2") + " textarea").type( - "{end}{backspace}{backspace}-2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("65% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is positive"); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "First is larger than second", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Sum of first two is larger than 5!", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.65"); - - cy.get(cesc("#\\/mi2") + " textarea").type( - "{end}{backspace}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("75% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is positive"); - cy.get(cesc("#\\/fb2")).should("have.text", "Second is positive"); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Sum of first two is larger than 5!", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.75"); - - cy.get(cesc("#\\/mi2") + " textarea").type( - "{end}{backspace}{backspace}11{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("90% correct"); - }); - - cy.get(cesc("#\\/fb1")).should("have.text", "First is positive"); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "Sum of first two is larger than 5!", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Sum of second and third is larger than 5!", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.9"); - - cy.get(cesc("#\\/mi3") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("be.visible"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "Sum of first two is larger than 5!", - ); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "Sum of first and third is larger than 5!", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Sum of second and third is larger than 5!", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - - cy.get(cesc("#\\/mi3") + " textarea").type( - "{end}{backspace}{backspace}6{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("be.visible"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "Sum of first two is larger than 5!", - ); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "Sum of first and third is larger than 5!", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Sum of second and third is larger than 5!", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{end}{backspace}{backspace}15{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("be.visible"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "Sum of first two is larger than 5!", - ); - cy.get(cesc("#\\/fb2")).should( - "have.text", - "Sum of first and third is larger than 5!", - ); - cy.get(cesc("#\\/fb3")).should( - "have.text", - "Sum of second and third is larger than 5!", - ); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - }); - - it("number of awards credited, zero credits are triggered", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - - - $mi1=x and $mi2=y and $mi3=z - - - $mi1!=x and $mi2!=y and $mi3!=z - - - $mi2=x or $mi3=x - - - $mi1=y or $mi3=y - - - $mi1=z or $mi2=z - - -

- - $a.feedbacks{assignNames="fb1 fb2 fb3 fb4 fb5"} - -

Credit: $a.creditAchieved{assignNames="ca"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let submitAnchor = cesc2("#/a_submit"); - let correctAnchor = cesc2("#/a_correct"); - let incorrectAnchor = cesc2("#/a_incorrect"); - let partialAnchor = cesc2("#/a_partial"); - - cy.get(submitAnchor).should("be.visible"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should("not.exist"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "Nothing is in the right spot", - ); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi1") + " textarea").type("z{enter}", { force: true }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "Nothing is in the right spot", - ); - cy.get(cesc("#\\/fb2")).should("have.text", "z is in the wrong spot"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi2") + " textarea").type("y{enter}", { force: true }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("33% correct"); - }); - cy.get(cesc("#\\/fb1")).should("have.text", "z is in the wrong spot"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.333"); - - cy.get(cesc("#\\/mi3") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("33% correct"); - }); - cy.get(cesc("#\\/fb1")).should("have.text", "x is in the wrong spot"); - cy.get(cesc("#\\/fb2")).should("have.text", "z is in the wrong spot"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.333"); - - cy.get(cesc("#\\/mi1") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("33% correct"); - }); - cy.get(cesc("#\\/fb1")).should("have.text", "x is in the wrong spot"); - cy.get(cesc("#\\/fb2")).should("have.text", "y is in the wrong spot"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.333"); - - cy.get(cesc("#\\/mi2") + " textarea").type("{end}{backspace}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("be.visible"); - cy.get(partialAnchor).should("not.exist"); - - cy.get(cesc("#\\/fb1")).should( - "have.text", - "Nothing is in the right spot", - ); - cy.get(cesc("#\\/fb2")).should("have.text", "x is in the wrong spot"); - cy.get(cesc("#\\/fb3")).should("have.text", "y is in the wrong spot"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi2") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi3") + " textarea").type("{end}{backspace}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("not.exist"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("67% correct"); - }); - cy.get(cesc("#\\/fb1")).should("have.text", "y is in the wrong spot"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "0.667"); - - cy.get(cesc("#\\/mi1") + " textarea").type("{end}{backspace}x{enter}", { - force: true, - }); - cy.get(cesc("#\\/a_submit")).click(); - - cy.get(submitAnchor).should("not.exist"); - cy.get(correctAnchor).should("be.visible"); - cy.get(incorrectAnchor).should("not.exist"); - cy.get(partialAnchor).should("not.exist"); - cy.get(cesc("#\\/fb1")).should("not.exist"); - cy.get(cesc("#\\/fb2")).should("not.exist"); - cy.get(cesc("#\\/fb3")).should("not.exist"); - cy.get(cesc("#\\/fb4")).should("not.exist"); - cy.get(cesc("#\\/fb5")).should("not.exist"); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - }); - - it("numSubmissions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- x+y -

-

hello

-

Number of submissions 1: $_answer1.numSubmissions{assignNames="nsubs1"}

-

Number of submissions 2: $_answer2.numSubmissions{assignNames="nsubs2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/nsubs1")).should("have.text", 0); - cy.get(cesc("#\\/nsubs2")).should("have.text", 0); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_answer1"].stateValues.numSubmissions).eq( - 0, - ); - expect(stateVariables["/nsubs1"].stateValues.value).eq(0); - expect(stateVariables["/_answer2"].stateValues.numSubmissions).eq( - 0, - ); - expect(stateVariables["/nsubs2"].stateValues.value).eq(0); - - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - - let textinputName = - stateVariables["/_answer2"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName + "_input"); - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - - cy.get(mathinputAnchor).type("x+y{enter}", { force: true }); - - cy.get(cesc("#\\/nsubs1")).should("have.text", 1); - cy.get(cesc("#\\/nsubs2")).should("have.text", 0); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.numSubmissions, - ).eq(1); - expect(stateVariables["/nsubs1"].stateValues.value).eq(1); - expect( - stateVariables["/_answer2"].stateValues.numSubmissions, - ).eq(0); - expect(stateVariables["/nsubs2"].stateValues.value).eq(0); - }); - - cy.get(mathinputAnchor).type("{end}{backspace}{backspace}", { - force: true, - }); - - cy.get(cesc("#\\/nsubs1")).should("have.text", 1); - cy.get(cesc("#\\/nsubs2")).should("have.text", 0); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.numSubmissions, - ).eq(1); - expect(stateVariables["/nsubs1"].stateValues.value).eq(1); - expect( - stateVariables["/_answer2"].stateValues.numSubmissions, - ).eq(0); - expect(stateVariables["/nsubs2"].stateValues.value).eq(0); - }); - - cy.get(textinputAnchor).type("h").blur(); - cy.get(cesc("#\\/nsubs1")).should("have.text", 1); - cy.get(cesc("#\\/nsubs2")).should("have.text", 0); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.numSubmissions, - ).eq(1); - expect(stateVariables["/nsubs1"].stateValues.value).eq(1); - expect( - stateVariables["/_answer2"].stateValues.numSubmissions, - ).eq(0); - expect(stateVariables["/nsubs2"].stateValues.value).eq(0); - }); - - cy.get(mathinputSubmitAnchor).click(); - - cy.get(cesc("#\\/nsubs1")).should("have.text", 2); - cy.get(cesc("#\\/nsubs2")).should("have.text", 0); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.numSubmissions, - ).eq(2); - expect(stateVariables["/nsubs1"].stateValues.value).eq(2); - expect( - stateVariables["/_answer2"].stateValues.numSubmissions, - ).eq(0); - expect(stateVariables["/nsubs2"].stateValues.value).eq(0); - }); - - cy.get(textinputSubmitAnchor).click(); - - cy.get(cesc("#\\/nsubs1")).should("have.text", 2); - cy.get(cesc("#\\/nsubs2")).should("have.text", 1); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.numSubmissions, - ).eq(2); - expect(stateVariables["/nsubs1"].stateValues.value).eq(2); - expect( - stateVariables["/_answer2"].stateValues.numSubmissions, - ).eq(1); - expect(stateVariables["/nsubs2"].stateValues.value).eq(1); - }); - - cy.get(textinputAnchor).clear().type("hello").blur(); - cy.get(mathinputAnchor).type("{end}+y", { force: true }).blur(); - - cy.get(cesc("#\\/nsubs1")).should("have.text", 2); - cy.get(cesc("#\\/nsubs2")).should("have.text", 1); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.numSubmissions, - ).eq(2); - expect(stateVariables["/nsubs1"].stateValues.value).eq(2); - expect( - stateVariables["/_answer2"].stateValues.numSubmissions, - ).eq(1); - expect(stateVariables["/nsubs2"].stateValues.value).eq(1); - }); - - cy.get(mathinputSubmitAnchor).click(); - cy.get(cesc("#\\/nsubs1")).should("have.text", 3); - cy.get(cesc("#\\/nsubs2")).should("have.text", 1); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.numSubmissions, - ).eq(3); - expect(stateVariables["/nsubs1"].stateValues.value).eq(3); - expect( - stateVariables["/_answer2"].stateValues.numSubmissions, - ).eq(1); - expect(stateVariables["/nsubs2"].stateValues.value).eq(1); - }); - - cy.get(textinputSubmitAnchor).click(); - cy.get(cesc("#\\/nsubs1")).should("have.text", 3); - cy.get(cesc("#\\/nsubs2")).should("have.text", 2); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.numSubmissions, - ).eq(3); - expect(stateVariables["/nsubs1"].stateValues.value).eq(3); - expect( - stateVariables["/_answer2"].stateValues.numSubmissions, - ).eq(2); - expect(stateVariables["/nsubs2"].stateValues.value).eq(2); - }); - }); - }); - - it("answer with choiceinput inside invalid child logic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - 1 - 2 - 3 - 4 - 5 - - - - $choice1.selectedValue{name="sv"} - - - $choice1.selectedValue = 4 - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Select correct answer"); - cy.get(cesc("#\\/choice1")).select(`4`); - cy.get(cesc("#\\/sv")).should("have.text", "4"); - cy.get(cesc("#\\/_answer1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("check work"); - }); - cy.get(cesc("#\\/_answer1_correct")).should("not.exist"); - cy.get(cesc("#\\/_answer1_incorrect")).should("not.exist"); - cy.get(cesc("#\\/_answer1_partial")).should("not.exist"); - - cy.log("Submit answer"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_answer1_correct")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("correct"); - }); - - cy.log("Select incorrect answer and submit"); - cy.get(cesc("#\\/choice1")).select(`3`); - cy.get(cesc("#\\/sv")).should("have.text", "3"); - cy.get(cesc("#\\/_answer1_submit")).click(); - cy.get(cesc("#\\/_answer1_incorrect")) - .invoke("text") - .then((text) => { - expect(text.trim().toLowerCase()).equal("incorrect"); - }); - }); - - it("maximum number of attempts", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x

-

x

-

x

-

x

- -

hello

-

hello

-

hello

-

hello

- -

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

- -

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

- -

true

-

true

-

true

-

true

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let inputNames = [...Array(20).keys()].map( - (n) => - stateVariables[`/_answer${n + 1}`].stateValues - .inputChildren[0].componentName, - ); - - cy.log("Submit correct answers"); - cy.get(cesc2("#" + inputNames[0]) + " textarea").type("x{enter}", { - force: true, - }); - cy.get(cesc2("#" + inputNames[1]) + " textarea").type("x{enter}", { - force: true, - }); - cy.get(cesc2("#" + inputNames[2]) + " textarea").type("x{enter}", { - force: true, - }); - cy.get(cesc2("#" + inputNames[3]) + " textarea").type("x{enter}", { - force: true, - }); - cy.get(cesc2("#/_answer3_submit")).click(); - cy.get(cesc2("#/_answer4_submit")).click(); - cy.get(cesc2("#" + inputNames[0]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[1]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer3_correct")).should("be.visible"); - cy.get(cesc2("#/_answer4_correct")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[4]) + "_input").type("hello{enter}"); - cy.get(cesc2("#" + inputNames[5]) + "_input").type("hello{enter}"); - cy.get(cesc2("#" + inputNames[6]) + "_input").type("hello{enter}"); - cy.get(cesc2("#" + inputNames[7]) + "_input").type("hello{enter}"); - cy.get(cesc2("#/_answer7_submit")).click(); - cy.get(cesc2("#/_answer8_submit")).click(); - cy.get(cesc2("#" + inputNames[4]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[5]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer7_correct")).should("be.visible"); - cy.get(cesc2("#/_answer8_correct")).should("be.visible"); - - cy.get(cesc2("#/_choiceinput1")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput2")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput3")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput4")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput2_submit")).click(); - cy.get(cesc2("#/_answer11_submit")).click(); - cy.get(cesc2("#/_answer12_submit")).click(); - cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc2("#/_choiceinput2_correct")).should("be.visible"); - cy.get(cesc2("#/_answer11_correct")).should("be.visible"); - cy.get(cesc2("#/_answer12_correct")).should("be.visible"); - - cy.get(cesc("#\\/_choiceinput5")).select(`yes`); - cy.get(cesc("#\\/_choiceinput6")).select(`yes`); - cy.get(cesc("#\\/_choiceinput7")).select(`yes`); - cy.get(cesc("#\\/_choiceinput8")).select(`yes`); - cy.get(cesc2("#/_choiceinput5_submit")).click(); - cy.get(cesc2("#/_choiceinput6_submit")).click(); - cy.get(cesc2("#/_answer15_submit")).click(); - cy.get(cesc2("#/_answer16_submit")).click(); - cy.get(cesc2("#/_choiceinput5_correct")).should("be.visible"); - cy.get(cesc2("#/_choiceinput6_correct")).should("be.visible"); - cy.get(cesc2("#/_answer15_correct")).should("be.visible"); - cy.get(cesc2("#/_answer16_correct")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[16])).click(); - cy.get(cesc2("#" + inputNames[17])).click(); - cy.get(cesc2("#" + inputNames[18])).click(); - cy.get(cesc2("#" + inputNames[19])).click(); - cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); - cy.get(cesc2("#" + inputNames[17]) + "_submit").click(); - cy.get(cesc2("#/_answer19_submit")).click(); - cy.get(cesc2("#/_answer20_submit")).click(); - cy.get(cesc2("#" + inputNames[16]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[17]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer19_correct")).should("be.visible"); - cy.get(cesc2("#/_answer20_correct")).should("be.visible"); - - cy.log("Submit incorrect answers"); - cy.get(cesc2("#" + inputNames[0]) + " textarea").type( - "{end}{backspace}y", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[1]) + " textarea").type( - "{end}{backspace}y", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[2]) + " textarea").type( - "{end}{backspace}y", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[3]) + " textarea").type( - "{end}{backspace}y", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[0]) + "_submit").click(); - cy.get(cesc2("#" + inputNames[1]) + "_submit").click(); - cy.get(cesc2("#/_answer3_submit")).click(); - cy.get(cesc2("#/_answer4_submit")).click(); - cy.get(cesc2("#" + inputNames[0]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[1]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer3_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer4_incorrect")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[4]) + "_input") - .clear() - .type("bye"); - cy.get(cesc2("#" + inputNames[5]) + "_input") - .clear() - .type("bye"); - cy.get(cesc2("#" + inputNames[6]) + "_input") - .clear() - .type("bye"); - cy.get(cesc2("#" + inputNames[7]) + "_input") - .clear() - .type("bye"); - cy.get(cesc2("#" + inputNames[4]) + "_submit").click(); - cy.get(cesc2("#" + inputNames[5]) + "_submit").click(); - cy.get(cesc2("#/_answer7_submit")).click(); - cy.get(cesc2("#/_answer8_submit")).click(); - cy.get(cesc2("#" + inputNames[4]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[5]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer7_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer8_incorrect")).should("be.visible"); - - cy.get(cesc2("#/_choiceinput1")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput2")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput3")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput4")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput2_submit")).click(); - cy.get(cesc2("#/_answer11_submit")).click(); - cy.get(cesc2("#/_answer12_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput2_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer11_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer12_incorrect")).should("be.visible"); - - cy.get(cesc("#\\/_choiceinput5")).select(`no`); - cy.get(cesc("#\\/_choiceinput6")).select(`no`); - cy.get(cesc("#\\/_choiceinput7")).select(`no`); - cy.get(cesc("#\\/_choiceinput8")).select(`no`); - cy.get(cesc2("#/_choiceinput5_submit")).click(); - cy.get(cesc2("#/_choiceinput6_submit")).click(); - cy.get(cesc2("#/_answer15_submit")).click(); - cy.get(cesc2("#/_answer16_submit")).click(); - cy.get(cesc2("#/_choiceinput5_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput6_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer15_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer16_incorrect")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[16])).click(); - cy.get(cesc2("#" + inputNames[17])).click(); - cy.get(cesc2("#" + inputNames[18])).click(); - cy.get(cesc2("#" + inputNames[19])).click(); - cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); - cy.get(cesc2("#" + inputNames[17]) + "_submit").click(); - cy.get(cesc2("#/_answer19_submit")).click(); - cy.get(cesc2("#/_answer20_submit")).click(); - cy.get(cesc2("#" + inputNames[16]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[17]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer19_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer20_incorrect")).should("be.visible"); - - cy.log("Type to submit correct answers again"); - - // the 2nd and 4th input should be disabled, - // but this isn't working yet. - // For now, best we can do is make sure button still say incorrect - cy.get(cesc2("#" + inputNames[0]) + " textarea").type( - "{end}{backspace}x", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[1]) + " textarea").type( - "{end}{backspace}x", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[2]) + " textarea").type( - "{end}{backspace}x", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[3]) + " textarea").type( - "{end}{backspace}x", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[0]) + "_submit").click(); - cy.get(cesc2("#/_answer3_submit")).click(); - cy.get(cesc2("#" + inputNames[0]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[1]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer3_correct")).should("be.visible"); - cy.get(cesc2("#/_answer4_incorrect")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[4]) + "_input") - .clear() - .type("hello"); - cy.get(cesc2("#" + inputNames[5]) + "_input").should("be.disabled"); - cy.get(cesc2("#" + inputNames[6]) + "_input") - .clear() - .type("hello"); - cy.get(cesc2("#" + inputNames[7]) + "_input").should("be.disabled"); - cy.get(cesc2("#" + inputNames[4]) + "_submit").click(); - cy.get(cesc2("#/_answer7_submit")).click(); - cy.get(cesc2("#" + inputNames[4]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[5]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer7_correct")).should("be.visible"); - cy.get(cesc2("#/_answer8_incorrect")).should("be.visible"); - - cy.get(cesc2("#/_choiceinput1")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput2")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput3")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput4")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_answer11_submit")).click(); - cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc2("#/_choiceinput2_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer11_correct")).should("be.visible"); - cy.get(cesc2("#/_answer12_incorrect")).should("be.visible"); - - cy.get(cesc("#\\/_choiceinput5")).select(`yes`); - cy.get(cesc("#\\/_choiceinput6")).should("be.disabled"); - cy.get(cesc("#\\/_choiceinput7")).select(`yes`); - cy.get(cesc("#\\/_choiceinput8")).should("be.disabled"); - cy.get(cesc2("#/_choiceinput5_submit")).click(); - cy.get(cesc2("#/_answer15_submit")).click(); - cy.get(cesc2("#/_choiceinput5_correct")).should("be.visible"); - cy.get(cesc2("#/_choiceinput6_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer15_correct")).should("be.visible"); - cy.get(cesc2("#/_answer16_incorrect")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[16])).click(); - cy.get(cesc2("#" + inputNames[17]) + "_input").should( - "be.disabled", - ); - cy.get(cesc2("#" + inputNames[18])).click(); - cy.get(cesc2("#" + inputNames[19]) + "_input").should( - "be.disabled", - ); - cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); - cy.get(cesc2("#/_answer19_submit")).click(); - cy.get(cesc2("#" + inputNames[16]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[17]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer19_correct")).should("be.visible"); - cy.get(cesc2("#/_answer20_incorrect")).should("be.visible"); - }); - }); - - it("disable after correct", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x

-

x

-

x

-

x

- -

hello

-

hello

-

hello

-

hello

- -

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

- -

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

- -

true

-

true

-

true

-

true

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let inputNames = [...Array(20).keys()].map( - (n) => - stateVariables[`/_answer${n + 1}`].stateValues - .inputChildren[0].componentName, - ); - - cy.log("Submit incorrect answers"); - cy.get(cesc2("#" + inputNames[0]) + " textarea").type("y{enter}", { - force: true, - }); - cy.get(cesc2("#" + inputNames[1]) + " textarea").type("y{enter}", { - force: true, - }); - cy.get(cesc2("#" + inputNames[2]) + " textarea").type("y{enter}", { - force: true, - }); - cy.get(cesc2("#" + inputNames[3]) + " textarea").type("y{enter}", { - force: true, - }); - cy.get(cesc2("#/_answer3_submit")).click(); - cy.get(cesc2("#/_answer4_submit")).click(); - cy.get(cesc2("#" + inputNames[0]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[1]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer3_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer4_incorrect")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[4]) + "_input").type("bye{enter}"); - cy.get(cesc2("#" + inputNames[5]) + "_input").type("bye{enter}"); - cy.get(cesc2("#" + inputNames[6]) + "_input").type("bye{enter}"); - cy.get(cesc2("#" + inputNames[7]) + "_input").type("bye{enter}"); - cy.get(cesc2("#/_answer7_submit")).click(); - cy.get(cesc2("#/_answer8_submit")).click(); - cy.get(cesc2("#" + inputNames[4]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[5]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer7_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer8_incorrect")).should("be.visible"); - - cy.get(cesc2("#/_choiceinput1")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput2")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput3")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput4")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput2_submit")).click(); - cy.get(cesc2("#/_answer11_submit")).click(); - cy.get(cesc2("#/_answer12_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput2_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer11_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer12_incorrect")).should("be.visible"); - - cy.get(cesc("#\\/_choiceinput5")).select(`no`); - cy.get(cesc("#\\/_choiceinput6")).select(`no`); - cy.get(cesc("#\\/_choiceinput7")).select(`no`); - cy.get(cesc("#\\/_choiceinput8")).select(`no`); - cy.get(cesc2("#/_choiceinput5_submit")).click(); - cy.get(cesc2("#/_choiceinput6_submit")).click(); - cy.get(cesc2("#/_answer15_submit")).click(); - cy.get(cesc2("#/_answer16_submit")).click(); - cy.get(cesc2("#/_choiceinput5_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput6_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer15_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer16_incorrect")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); - cy.get(cesc2("#" + inputNames[17]) + "_submit").click(); - cy.get(cesc2("#/_answer19_submit")).click(); - cy.get(cesc2("#/_answer20_submit")).click(); - cy.get(cesc2("#" + inputNames[16]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[17]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#/_answer19_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer20_incorrect")).should("be.visible"); - - cy.log("Submit correct answers"); - cy.get(cesc2("#" + inputNames[0]) + " textarea").type( - "{end}{backspace}x", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[1]) + " textarea").type( - "{end}{backspace}x", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[2]) + " textarea").type( - "{end}{backspace}x", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[3]) + " textarea").type( - "{end}{backspace}x", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[0]) + "_submit").click(); - cy.get(cesc2("#" + inputNames[1]) + "_submit").click(); - cy.get(cesc2("#/_answer3_submit")).click(); - cy.get(cesc2("#/_answer4_submit")).click(); - cy.get(cesc2("#" + inputNames[0]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[1]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer3_correct")).should("be.visible"); - cy.get(cesc2("#/_answer4_correct")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[4]) + "_input") - .clear() - .type("hello"); - cy.get(cesc2("#" + inputNames[5]) + "_input") - .clear() - .type("hello"); - cy.get(cesc2("#" + inputNames[6]) + "_input") - .clear() - .type("hello"); - cy.get(cesc2("#" + inputNames[7]) + "_input") - .clear() - .type("hello"); - cy.get(cesc2("#" + inputNames[4]) + "_submit").click(); - cy.get(cesc2("#" + inputNames[5]) + "_submit").click(); - cy.get(cesc2("#/_answer7_submit")).click(); - cy.get(cesc2("#/_answer8_submit")).click(); - cy.get(cesc2("#" + inputNames[4]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[5]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer7_correct")).should("be.visible"); - cy.get(cesc2("#/_answer8_correct")).should("be.visible"); - - cy.get(cesc2("#/_choiceinput1")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput2")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput3")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput4")) - .contains("yes") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput2_submit")).click(); - cy.get(cesc2("#/_answer11_submit")).click(); - cy.get(cesc2("#/_answer12_submit")).click(); - cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc2("#/_choiceinput2_correct")).should("be.visible"); - cy.get(cesc2("#/_answer11_correct")).should("be.visible"); - cy.get(cesc2("#/_answer12_correct")).should("be.visible"); - - cy.get(cesc("#\\/_choiceinput5")).select(`yes`); - cy.get(cesc("#\\/_choiceinput6")).select(`yes`); - cy.get(cesc("#\\/_choiceinput7")).select(`yes`); - cy.get(cesc("#\\/_choiceinput8")).select(`yes`); - cy.get(cesc2("#/_choiceinput5_submit")).click(); - cy.get(cesc2("#/_choiceinput6_submit")).click(); - cy.get(cesc2("#/_answer15_submit")).click(); - cy.get(cesc2("#/_answer16_submit")).click(); - cy.get(cesc2("#/_choiceinput5_correct")).should("be.visible"); - cy.get(cesc2("#/_choiceinput6_correct")).should("be.visible"); - cy.get(cesc2("#/_answer15_correct")).should("be.visible"); - cy.get(cesc2("#/_answer16_correct")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[16])).click(); - cy.get(cesc2("#" + inputNames[17])).click(); - cy.get(cesc2("#" + inputNames[18])).click(); - cy.get(cesc2("#" + inputNames[19])).click(); - cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); - cy.get(cesc2("#" + inputNames[17]) + "_submit").click(); - cy.get(cesc2("#/_answer19_submit")).click(); - cy.get(cesc2("#/_answer20_submit")).click(); - cy.get(cesc2("#" + inputNames[16]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[17]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer19_correct")).should("be.visible"); - cy.get(cesc2("#/_answer20_correct")).should("be.visible"); - - cy.log("Type to submit incorrect answers again"); - - // the 2nd and 4th input should be disabled, - // but this isn't working yet. - // For now, best we can do is make sure button still say incorrect - cy.get(cesc2("#" + inputNames[0]) + " textarea").type( - "{end}{backspace}y", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[1]) + " textarea").type( - "{end}{backspace}y", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[2]) + " textarea").type( - "{end}{backspace}y", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[3]) + " textarea").type( - "{end}{backspace}y", - { force: true }, - ); - cy.get(cesc2("#" + inputNames[0]) + "_submit").click(); - cy.get(cesc2("#/_answer3_submit")).click(); - cy.get(cesc2("#" + inputNames[0]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[1]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer3_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer4_correct")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[4]) + "_input") - .clear() - .type("bye"); - cy.get(cesc2("#" + inputNames[5]) + "_input").should("be.disabled"); - cy.get(cesc2("#" + inputNames[6]) + "_input") - .clear() - .type("bye"); - cy.get(cesc2("#" + inputNames[7]) + "_input").should("be.disabled"); - cy.get(cesc2("#" + inputNames[4]) + "_submit").click(); - cy.get(cesc2("#/_answer7_submit")).click(); - cy.get(cesc2("#" + inputNames[4]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[5]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer7_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer8_correct")).should("be.visible"); - - cy.get(cesc2("#/_choiceinput1")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput2")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput3")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput4")) - .contains("no") - .click({ force: true }); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_answer11_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput2_correct")).should("be.visible"); - cy.get(cesc2("#/_answer11_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer12_correct")).should("be.visible"); - - cy.get(cesc("#\\/_choiceinput5")).select(`no`); - cy.get(cesc("#\\/_choiceinput6")).should("be.disabled"); - cy.get(cesc("#\\/_choiceinput7")).select(`no`); - cy.get(cesc("#\\/_choiceinput8")).should("be.disabled"); - cy.get(cesc2("#/_choiceinput5_submit")).click(); - cy.get(cesc2("#/_answer15_submit")).click(); - cy.get(cesc2("#/_choiceinput5_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput6_correct")).should("be.visible"); - cy.get(cesc2("#/_answer15_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer16_correct")).should("be.visible"); - - cy.get(cesc2("#" + inputNames[16])).click(); - cy.get(cesc2("#" + inputNames[17]) + "_input").should( - "be.disabled", - ); - cy.get(cesc2("#" + inputNames[18])).click(); - cy.get(cesc2("#" + inputNames[19]) + "_input").should( - "be.disabled", - ); - cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); - cy.get(cesc2("#/_answer19_submit")).click(); - cy.get(cesc2("#" + inputNames[16]) + "_incorrect").should( - "be.visible", - ); - cy.get(cesc2("#" + inputNames[17]) + "_correct").should( - "be.visible", - ); - cy.get(cesc2("#/_answer19_incorrect")).should("be.visible"); - cy.get(cesc2("#/_answer20_correct")).should("be.visible"); - }); - }); - - it("disable after correct, depends on external", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - (3,4) - (-5,6) - - - - -

Move point to (3,4):

-

- - $A = (3,4) - -

-

- - $A = (3,4) - -

- -

Move point to (-5,6):

-

- - $A = (-5,6) - -

-

- - $A = (-5,6) - -

- -

- -

Enter x in above blank.

-

- $mi=x -

-

- $mi=x -

- -

Enter y in above blank.

-

- $mi=y -

-

- $mi=y -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Submit incorrect answers"); - for (let i = 1; i <= 8; i++) { - cy.get(cesc(`#\\/_answer${i}_submit`)).click(); - cy.get(cesc(`#\\/_answer${i}_incorrect`)).should("be.visible"); - } - - cy.log("submit first correct answers"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: 3, y: 4 }, - }); - }); - cy.get(cesc("#\\/mi") + " textarea").type("x{enter}", { force: true }); - - for (let i = 1; i <= 8; i++) { - cy.get(cesc(`#\\/_answer${i}_submit`)).click(); - if (i % 4 === 1 || i % 4 == 2) { - cy.get(cesc(`#\\/_answer${i}_correct`)).should("be.visible"); - } else { - cy.get(cesc(`#\\/_answer${i}_incorrect`)).should("be.visible"); - } - } - - cy.log("submit second correct answers"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: -5, y: 6 }, - }); - }); - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - - for (let i = 1; i <= 8; i++) { - if (i % 4 !== 2) { - cy.get(cesc(`#\\/_answer${i}_submit`)).click(); - } - if (i % 4 === 1) { - cy.get(cesc(`#\\/_answer${i}_incorrect`)).should("be.visible"); - } else { - cy.get(cesc(`#\\/_answer${i}_correct`)).should("be.visible"); - } - } - - cy.log("submit second incorrect answers"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: 1, y: -1 }, - }); - }); - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}z{enter}", { - force: true, - }); - - for (let i = 1; i <= 8; i++) { - if (i % 4 === 2 || i % 4 === 0) { - cy.get(cesc(`#\\/_answer${i}_correct`)).should("be.visible"); - } else { - cy.get(cesc(`#\\/_answer${i}_submit`)).click(); - cy.get(cesc(`#\\/_answer${i}_incorrect`)).should("be.visible"); - } - } - }); - - it("award based on choice text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - cat - dog - monkey - - $_choiceinput1 = $ca.text - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1")).select(`cat`); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_correct")).should("be.visible"); - - cy.get(cesc("#\\/_choiceinput1")).select(`dog`); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - - cy.get(cesc("#\\/_choiceinput1")).select(`monkey`); - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput1_incorrect")).should("be.visible"); - }); - - it("error expressions are not matched", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^ - x^ - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinput1Name = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinput1Anchor = cesc2("#" + mathinput1Name) + " textarea"; - let mathinput1SubmitAnchor = cesc2( - "#" + mathinput1Name + "_submit", - ); - let mathinput1CorrectAnchor = cesc2( - "#" + mathinput1Name + "_correct", - ); - let mathinput1IncorrectAnchor = cesc2( - "#" + mathinput1Name + "_incorrect", - ); - - let mathinput2Name = - stateVariables["/_answer2"].stateValues.inputChildren[0] - .componentName; - let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - let mathinput2SubmitAnchor = cesc2( - "#" + mathinput2Name + "_submit", - ); - let mathinput2CorrectAnchor = cesc2( - "#" + mathinput2Name + "_correct", - ); - let mathinput2IncorrectAnchor = cesc2( - "#" + mathinput2Name + "_incorrect", - ); - - cy.get(mathinput1SubmitAnchor).click(); - cy.get(mathinput1IncorrectAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).click(); - cy.get(mathinput2IncorrectAnchor).should("be.visible"); - - cy.get(mathinput1Anchor).type("x^{enter}", { force: true }); - cy.get(mathinput1IncorrectAnchor).should("be.visible"); - cy.get(mathinput2Anchor).type("x^{enter}", { force: true }); - cy.get(mathinput2IncorrectAnchor).should("be.visible"); - - cy.get(mathinput1Anchor).type("{end}{leftArrow}2{enter}", { - force: true, - }); - cy.get(mathinput1IncorrectAnchor).should("be.visible"); - cy.get(mathinput2Anchor).type("{end}{leftArrow}2{enter}", { - force: true, - }); - cy.get(mathinput2IncorrectAnchor).should("be.visible"); - }); - }); - - it("with split symbols, specified directly on mathinput and math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

split symbols:

-

Answer: xyz

- - - $ans - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mi") + " textarea").type("xyz{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi_correct")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ans"].stateValues.value).eqls("xyz"); - expect(stateVariables["/mi"].stateValues.value).eqls("xyz"); - }); - - cy.get(cesc("#\\/split")).click(); - - // modify mathinput so that recalculates value - cy.get(cesc("#\\/mi") + " textarea").type("{end}a{backspace}", { - force: true, - }); - cy.get(cesc("#\\/mi_submit")).click(); - cy.get(cesc("#\\/mi_correct")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ans"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - }); - - cy.get(cesc("#\\/split")).click(); - - // modify mathinput so that recalculates value - cy.get(cesc("#\\/mi") + " textarea").type("{end}b{backspace}", { - force: true, - }); - cy.get(cesc("#\\/mi_submit")).click(); - - cy.get(cesc("#\\/mi_correct")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ans"].stateValues.value).eqls("xyz"); - expect(stateVariables["/mi"].stateValues.value).eqls("xyz"); - }); - }); - - it("with split symbols, sugared answer", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

split symbols:

- xyz - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mathinputName = - stateVariables["/_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", - ); - let mathName = - stateVariables[ - stateVariables["/_answer1"].activeChildren[1].componentName - ].activeChildren[0].componentName; - - cy.get(mathinputAnchor).type("xyz{enter}", { force: true }); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables[mathName].stateValues.value).eqls("xyz"); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "xyz", - ); - }); - - cy.get(cesc("#\\/split")).click(); - - // modify mathinput so that recalculates value - cy.get(mathinputAnchor).type("{end}a{backspace}", { force: true }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables[mathName].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - }); - - cy.get(cesc("#\\/split")).click(); - - // modify mathinput so that recalculates value - cy.get(mathinputAnchor).type("{end}b{backspace}", { force: true }); - cy.get(mathinputSubmitAnchor).click(); - - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables[mathName].stateValues.value).eqls("xyz"); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "xyz", - ); - }); - }); - }); - - it("with split symbols, shortcut award, sugared math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

split symbols:

- - xyz - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mathinputName = - stateVariables["/_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", - ); - let mathName = - stateVariables["/_award1"].activeChildren[0].componentName; - - cy.get(mathinputAnchor).type("xyz{enter}", { force: true }); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables[mathName].stateValues.value).eqls("xyz"); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "xyz", - ); - }); - - cy.get(cesc("#\\/split")).click(); - - // modify mathinput so that recalculates value - cy.get(mathinputAnchor).type("{end}a{backspace}", { force: true }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables[mathName].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables[mathinputName].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - }); - - cy.get(cesc("#\\/split")).click(); - - // modify mathinput so that recalculates value - cy.get(mathinputAnchor).type("{end}b{backspace}", { force: true }); - cy.get(mathinputSubmitAnchor).click(); - - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables[mathName].stateValues.value).eqls("xyz"); - expect(stateVariables[mathinputName].stateValues.value).eqls( - "xyz", - ); - }); - }); - }); - - it("with split symbols, explicit mathinput and math, but inferred split symbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

split symbols:

- - - xyz - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mi") + " textarea").type("xyz{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi_correct")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ans"].stateValues.value).eqls("xyz"); - expect(stateVariables["/mi"].stateValues.value).eqls("xyz"); - }); - - cy.get(cesc("#\\/split")).click(); - - // modify mathinput so that recalculates value - cy.get(cesc("#\\/mi") + " textarea").type("{end}a{backspace}", { - force: true, - }); - cy.get(cesc("#\\/mi_submit")).click(); - cy.get(cesc("#\\/mi_correct")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ans"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - }); - - cy.get(cesc("#\\/split")).click(); - - // modify mathinput so that recalculates value - cy.get(cesc("#\\/mi") + " textarea").type("{end}b{backspace}", { - force: true, - }); - cy.get(cesc("#\\/mi_submit")).click(); - - cy.get(cesc("#\\/mi_correct")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ans"].stateValues.value).eqls("xyz"); - expect(stateVariables["/mi"].stateValues.value).eqls("xyz"); - }); - }); - - it("justSubmitted with expression containing NaN", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 0/0+1 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mi") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/mi_incorrect")).should("be.visible"); - }); - - it("copy justSubmitted attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 1 - - -

The answer was just submitted.

-
- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mi_submit")).should("be.visible"); - cy.get(cesc("#\\/mi_correct")).should("not.exist"); - cy.get(cesc("#\\/mi_incorrect")).should("not.exist"); - cy.get(cesc("#\\/just")).should("not.exist"); - - cy.get(cesc("#\\/mi") + " textarea").type("x", { force: true }); - cy.get(cesc("#\\/mi_submit")).should("be.visible"); - cy.get(cesc("#\\/mi_correct")).should("not.exist"); - cy.get(cesc("#\\/mi_incorrect")).should("not.exist"); - cy.get(cesc("#\\/just")).should("not.exist"); - - cy.get(cesc("#\\/mi_submit")).click(); - cy.get(cesc("#\\/mi_submit")).should("not.exist"); - cy.get(cesc("#\\/mi_correct")).should("not.exist"); - cy.get(cesc("#\\/mi_incorrect")).should("be.visible"); - cy.get(cesc("#\\/just")).should( - "have.text", - "The answer was just submitted.", - ); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}1", { - force: true, - }); - cy.get(cesc("#\\/mi_submit")).should("be.visible"); - cy.get(cesc("#\\/mi_correct")).should("not.exist"); - cy.get(cesc("#\\/mi_incorrect")).should("not.exist"); - cy.get(cesc("#\\/just")).should("not.exist"); - - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - cy.get(cesc("#\\/mi_submit")).should("not.exist"); - cy.get(cesc("#\\/mi_correct")).should("be.visible"); - cy.get(cesc("#\\/mi_incorrect")).should("not.exist"); - cy.get(cesc("#\\/just")).should( - "have.text", - "The answer was just submitted.", - ); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}1", { - force: true, - }); - cy.get(cesc("#\\/mi_submit")).should("be.visible"); - cy.get(cesc("#\\/mi_correct")).should("not.exist"); - cy.get(cesc("#\\/mi_incorrect")).should("not.exist"); - cy.get(cesc("#\\/just")).should("not.exist"); - }); - - it("empty mathlists always equal", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - = - - - - - - - = - - - - - - - = - - - - - - - = - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/ans1_submit")).click(); - cy.get(cesc("#\\/ans1_correct")).should("be.visible"); - - cy.get(cesc("#\\/ans2_submit")).click(); - cy.get(cesc("#\\/ans2_correct")).should("be.visible"); - - cy.get(cesc("#\\/ans3_submit")).click(); - cy.get(cesc("#\\/ans3_correct")).should("be.visible"); - - cy.get(cesc("#\\/ans4_submit")).click(); - cy.get(cesc("#\\/ans4_correct")).should("be.visible"); - }); - - it("cannot change submitted or changed response", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - -

Current Response: $a.currentResponse{assignNames="cr"}

-

Submitted Response: $a.submittedResponse{assignNames="sr"}

- -

Change current response:

-

Change submitted response:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr")).should("not.exist"); - - cy.log("cannot change from mathinputs"); - cy.get(cesc("#\\/micr") + " textarea").type("y{enter}", { - force: true, - }); - cy.get(cesc("#\\/misr") + " textarea").type("z{enter}", { - force: true, - }); - - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr")).should("not.exist"); - - cy.log("submit response"); - cy.get(cesc("#\\/mia") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/cr") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - - cy.log("cannot change from mathinputs"); - cy.get(cesc("#\\/micr") + " textarea").type( - "{end}{backspace}y{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/misr") + " textarea").type( - "{end}{backspace}z{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - }); - - it("answer award with sugared string, copy award and overwrite properties", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

- 1.1 - -

-

Number of responses: $an.numResponses{name="nr"}

-

Submitted response: $an.submittedResponses{name="sr"}

-

First award awarded: $aw

-

First award awarded: $aw.awarded

-

First award awarded: $aw

-

First award awarded: $aw.awarded

-

First award awarded:

-

First award awarded:

-

Second award awarded: $aw2

-

Second award awarded: $aw2.awarded

-

Second award awarded: $aw2

-

Second award awarded: $aw2.awarded

-

Second award awarded:

-

Second award awarded:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/nr")).should("have.text", "1"); - - cy.get(cesc("#\\/pfa1")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa2")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa3")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa4")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa5")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa6")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/psa1")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa2")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa3")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa4")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa5")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa6")).should( - "have.text", - "Second award awarded: false", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/an"].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("1.1{enter}", { force: true }); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.1"); - }); - - cy.get(cesc("#\\/pfa1")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa2")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa3")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa4")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa5")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa6")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/psa1")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa2")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa3")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa4")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa5")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa6")).should( - "have.text", - "Second award awarded: false", - ); - - cy.get(mathinputAnchor).type("{end}1", { force: true }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - cy.get(mathinputPartialAnchor).should("not.exist"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.11"); - }); - - cy.get(cesc("#\\/pfa1")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa2")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa3")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa4")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa5")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa6")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/psa1")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa2")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa3")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa4")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa5")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa6")).should( - "have.text", - "Second award awarded: false", - ); - - cy.get(mathinputAnchor).type("{end}{leftArrow}0", { force: true }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("have.text", "50 %"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.101"); - }); - - cy.get(cesc("#\\/pfa1")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa2")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa3")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa4")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa5")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa6")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/psa1")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa2")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa3")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa4")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa5")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa6")).should( - "have.text", - "Second award awarded: true", - ); - }); - }); - - it("answer award with full award, copy award and overwrite properties", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

- - $mi=1.1 - -

-

Number of responses: $an.numResponses{name="nr"}

-

Submitted response: $an.submittedResponses{name="sr"}

-

First award awarded: $aw

-

First award awarded: $aw.awarded

-

First award awarded: $aw

-

First award awarded: $aw.awarded

-

First award awarded:

-

First award awarded:

-

Second award awarded: $aw2

-

Second award awarded: $aw2.awarded

-

Second award awarded: $aw2

-

Second award awarded: $aw2.awarded

-

Second award awarded:

-

Second award awarded:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/nr")).should("have.text", "1"); - - cy.get(cesc("#\\/pfa1")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa2")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa3")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa4")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa5")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa6")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/psa1")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa2")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa3")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa4")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa5")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa6")).should( - "have.text", - "Second award awarded: false", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/an"].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("1.1{enter}", { force: true }); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.1"); - }); - - cy.get(cesc("#\\/pfa1")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa2")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa3")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa4")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa5")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/pfa6")).should( - "have.text", - "First award awarded: true", - ); - cy.get(cesc("#\\/psa1")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa2")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa3")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa4")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa5")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa6")).should( - "have.text", - "Second award awarded: false", - ); - - cy.get(mathinputAnchor).type("{end}1", { force: true }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - cy.get(mathinputPartialAnchor).should("not.exist"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.11"); - }); - - cy.get(cesc("#\\/pfa1")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa2")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa3")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa4")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa5")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa6")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/psa1")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa2")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa3")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa4")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa5")).should( - "have.text", - "Second award awarded: false", - ); - cy.get(cesc("#\\/psa6")).should( - "have.text", - "Second award awarded: false", - ); - - cy.get(mathinputAnchor).type("{end}{leftArrow}0", { force: true }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("have.text", "50 %"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.101"); - }); - - cy.get(cesc("#\\/pfa1")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa2")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa3")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa4")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa5")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/pfa6")).should( - "have.text", - "First award awarded: false", - ); - cy.get(cesc("#\\/psa1")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa2")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa3")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa4")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa5")).should( - "have.text", - "Second award awarded: true", - ); - cy.get(cesc("#\\/psa6")).should( - "have.text", - "Second award awarded: true", - ); - }); - }); - - it("answer award with full award and outside input, copy award and overwrite properties", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - $mi=1.1 - -

-

Number of responses: $an.numResponses{name="nr"}

-

Submitted response: $an.submittedResponses{name="sr"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/nr")).should("have.text", "1"); - - cy.get(cesc("#\\/mi") + " textarea").type("1.1{enter}", { - force: true, - }); - cy.get(cesc("#\\/an_submit")).click(); - cy.get(cesc("#\\/an_correct")).should("be.visible"); - cy.get(cesc("#\\/an_incorrect")).should("not.exist"); - cy.get(cesc("#\\/an_partial")).should("not.exist"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.1"); - }); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}1{enter}", { - force: true, - }); - cy.get(cesc("#\\/an_submit")).click(); - cy.get(cesc("#\\/an_correct")).should("not.exist"); - cy.get(cesc("#\\/an_incorrect")).should("be.visible"); - cy.get(cesc("#\\/an_partial")).should("not.exist"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.11"); - }); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{leftArrow}0{enter}", { - force: true, - }); - cy.get(cesc("#\\/an_submit")).click(); - cy.get(cesc("#\\/an_correct")).should("not.exist"); - cy.get(cesc("#\\/an_incorrect")).should("not.exist"); - cy.get(cesc("#\\/an_partial")).should("have.text", "50% Correct"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1.101"); - }); - }); - - it("copied answer mirrors original", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+y

-

Current response: $ans1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $ans1.creditAchieved{assignNames="ca1"}

- -

-

Current response: $ans2.currentResponse{assignNames="cr2"}

-

Submitted response:

-

Credit for submitted response: $ans2.creditAchieved{name="ca2"}

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mathinput1Name = - stateVariables["/ans1"].stateValues.inputChildren[0] - .componentName; - let mathinput1Anchor = cesc2("#" + mathinput1Name) + " textarea"; - let mathinput1SubmitAnchor = cesc2( - "#" + mathinput1Name + "_submit", - ); - let mathinput1CorrectAnchor = cesc2( - "#" + mathinput1Name + "_correct", - ); - let mathinput1IncorrectAnchor = cesc2( - "#" + mathinput1Name + "_incorrect", - ); - - let mathinput2Name = - stateVariables["/ans2"].stateValues.inputChildren[0] - .componentName; - let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - let mathinput2SubmitAnchor = cesc2( - "#" + mathinput2Name + "_submit", - ); - let mathinput2CorrectAnchor = cesc2( - "#" + mathinput2Name + "_correct", - ); - let mathinput2IncorrectAnchor = cesc2( - "#" + mathinput2Name + "_incorrect", - ); - - cy.get(mathinput1SubmitAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - - cy.log("Type correct answer in first blank"); - - cy.get(mathinput1Anchor).type("x+y", { force: true }).blur(); - - cy.get(mathinput1SubmitAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).should("be.visible"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should("have.text", "x+y"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - - cy.log("Click second submit button"); - - cy.get(mathinput2SubmitAnchor).click(); - - cy.get(mathinput1CorrectAnchor).should("be.visible"); - cy.get(mathinput2CorrectAnchor).should("be.visible"); - - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should("have.text", "x+y"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "1"); - - cy.log("type incorrect answer into second blank"); - - cy.get(mathinput2Anchor) - .type("{end}{backspace}{backspace}", { force: true }) - .blur(); - - cy.get(mathinput1SubmitAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should("have.text", "x"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "1"); - - cy.log("Click first submit button"); - - cy.get(mathinput1SubmitAnchor).click(); - - cy.get(mathinput1IncorrectAnchor).should("be.visible"); - cy.get(mathinput2IncorrectAnchor).should("be.visible"); - - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should("have.text", "x"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - }); - }); - - it("copy answer with no link", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x+y

-

Current response: $ans1.currentResponse{assignNames="cr1"}

-

Submitted response:

-

Credit for submitted response: $ans1.creditAchieved{assignNames="ca1"}

- -

-

Current response: $ans2.currentResponse{assignNames="cr2"}

-

Submitted response:

-

Credit for submitted response: $ans2.creditAchieved{name="ca2"}

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mathinput1Name = - stateVariables["/ans1"].stateValues.inputChildren[0] - .componentName; - let mathinput1Anchor = cesc2("#" + mathinput1Name) + " textarea"; - let mathinput1SubmitAnchor = cesc2( - "#" + mathinput1Name + "_submit", - ); - let mathinput1CorrectAnchor = cesc2( - "#" + mathinput1Name + "_correct", - ); - let mathinput1IncorrectAnchor = cesc2( - "#" + mathinput1Name + "_incorrect", - ); - - let mathinput2Name = - stateVariables["/ans2"].stateValues.inputChildren[0] - .componentName; - let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - let mathinput2SubmitAnchor = cesc2( - "#" + mathinput2Name + "_submit", - ); - let mathinput2CorrectAnchor = cesc2( - "#" + mathinput2Name + "_correct", - ); - let mathinput2IncorrectAnchor = cesc2( - "#" + mathinput2Name + "_incorrect", - ); - - cy.get(mathinput1SubmitAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - - cy.log("Type correct answer in first blank"); - - cy.get(mathinput1Anchor).type("x+y", { force: true }).blur(); - - cy.get(mathinput1SubmitAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x+y"); - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - - cy.log("Click first submit button"); - - cy.get(mathinput1SubmitAnchor).click(); - - cy.get(mathinput1CorrectAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x+y"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - - cy.log("type correct answer into second blank"); - - cy.get(mathinput2Anchor).type("x+y", { force: true }).blur(); - - cy.get(mathinput1CorrectAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should("have.text", "x+y"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - - cy.log("Click second submit button"); - - cy.get(mathinput2SubmitAnchor).click(); - - cy.get(mathinput1CorrectAnchor).should("be.visible"); - cy.get(mathinput2CorrectAnchor).should("be.visible"); - - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should("have.text", "x+y"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "1"); - - cy.log("type incorrect answer into second blank"); - - cy.get(mathinput2Anchor) - .type("{end}{backspace}{backspace}", { force: true }) - .blur(); - - cy.get(mathinput1CorrectAnchor).should("be.visible"); - cy.get(mathinput2SubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow").should("have.text", "x"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "1"); - - cy.log("press enter in second blank"); - - cy.get(mathinput2Anchor).type("{enter}", { force: true }); - - cy.get(mathinput1CorrectAnchor).should("be.visible"); - cy.get(mathinput2IncorrectAnchor).should("be.visible"); - - cy.get(cesc("#\\/sr2") + " .mjx-mrow").should("have.text", "x"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - - cy.log("type incorrect answer into first blank"); - - cy.get(mathinput1Anchor) - .type("{end}{backspace}{backspace}", { force: true }) - .blur(); - - cy.get(mathinput1SubmitAnchor).should("be.visible"); - cy.get(mathinput2IncorrectAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow").should("have.text", "x"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x+y"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "1"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - - cy.log("press enter in first blank"); - - cy.get(mathinput1Anchor).type("{enter}", { force: true }); - - cy.get(mathinput1IncorrectAnchor).should("be.visible"); - cy.get(mathinput2IncorrectAnchor).should("be.visible"); - - cy.get(cesc("#\\/sr1") + " .mjx-mrow").should("have.text", "x"); - - cy.get(cesc("#\\/cr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/ca1")).should("have.text", "0"); - - cy.get(cesc("#\\/cr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - cy.get(cesc("#\\/ca2")).should("have.text", "0"); - }); - }); - - // TODO: is there any way to check this now that core is in a web worker? - it.skip("credit achieved not calculated before submit", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - x^2-2x+3 - x^2-2x+3 - -

Current response: $ans.currentResponse{assignNames="cr"}

-

Submitted response:

-

Credit for submitted response: $ans.creditAchieved{assignNames="ca"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - 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(mathinputSubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.log( - "check that have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit", - ); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let stateVarObj = - stateVariables["/_award1"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award1"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award2"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award2"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/ans"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - - expect(stateVariables["/ans"].state.creditAchieved.value).eq(0); - expect( - stateVariables["/_award1"].state.creditAchieved.value, - ).eq(0); - expect( - stateVariables["/_award1"].state.fractionSatisfied.value, - ).eq(0); - expect( - stateVariables["/_award2"].state.creditAchieved.value, - ).eq(0); - expect( - stateVariables["/_award2"].state.fractionSatisfied.value, - ).eq(0); - }); - - cy.log("type correct answer"); - - cy.get(mathinputAnchor) - .type("x^2{rightArrow}-2x+3", { force: true }) - .blur(); - - cy.get(mathinputSubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr") + " .mjx-mrow").should( - "contain.text", - "x2βˆ’2x+3", - ); - - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2βˆ’2x+3"); - }); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0"); - - cy.log( - "check that still have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit", - ); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let stateVarObj = - stateVariables["/_award1"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award1"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award2"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award2"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/ans"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - - expect(stateVariables["/ans"].state.creditAchieved.value).eq(0); - expect( - stateVariables["/_award1"].state.creditAchieved.value, - ).eq(0); - expect( - stateVariables["/_award1"].state.fractionSatisfied.value, - ).eq(0); - expect( - stateVariables["/_award2"].state.creditAchieved.value, - ).eq(0); - expect( - stateVariables["/_award2"].state.fractionSatisfied.value, - ).eq(0); - }); - - cy.log("click submit"); - - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2βˆ’2x+3"); - }); - cy.get(cesc("#\\/sr") + " .mjx-mrow").should( - "contain.text", - "x2βˆ’2x+3", - ); - - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2βˆ’2x+3"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - - cy.log( - "check that no longer have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit", - ); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let stateVarObj = - stateVariables["/_award1"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - stateVarObj = - stateVariables["/_award1"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - stateVarObj = - stateVariables["/_award2"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - stateVarObj = - stateVariables["/_award2"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - stateVarObj = - stateVariables["/ans"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - - expect( - stateVariables["/_award1"].state.creditAchievedIfSubmit - .value, - ).eq(1); - expect( - stateVariables["/_award1"].state.fractionSatisfiedIfSubmit - .value, - ).eq(1); - expect( - stateVariables["/_award1"].state.creditAchieved.value, - ).eq(1); - expect( - stateVariables["/_award1"].state.fractionSatisfied.value, - ).eq(1); - expect( - stateVariables["/_award2"].state.creditAchievedIfSubmit - .value, - ).eq(0.5); - expect( - stateVariables["/_award2"].state.fractionSatisfiedIfSubmit - .value, - ).eq(1); - expect( - stateVariables["/_award2"].state.creditAchieved.value, - ).eq(0.5); - expect( - stateVariables["/_award2"].state.fractionSatisfied.value, - ).eq(1); - expect( - stateVariables["/ans"].state.creditAchievedIfSubmit.value, - ).eq(1); - expect(stateVariables["/ans"].state.creditAchieved.value).eq(1); - }); - - cy.log("type partially correct answer"); - - cy.get(mathinputAnchor) - .type("{end}{leftArrow}{backspace}-", { force: true }) - .blur(); - - cy.get(mathinputSubmitAnchor).should("be.visible"); - - cy.get(cesc("#\\/cr") + " .mjx-mrow").should( - "contain.text", - "x2βˆ’2xβˆ’3", - ); - - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2βˆ’2xβˆ’3"); - }); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2βˆ’2x+3"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "1"); - - cy.log( - "check that still have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit", - ); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let stateVarObj = - stateVariables["/_award1"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award1"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award2"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/_award2"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - stateVarObj = - stateVariables["/ans"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.true; - - expect(stateVariables["/ans"].state.creditAchieved.value).eq(1); - expect( - stateVariables["/_award1"].state.creditAchieved.value, - ).eq(1); - expect( - stateVariables["/_award1"].state.fractionSatisfied.value, - ).eq(1); - expect( - stateVariables["/_award2"].state.creditAchieved.value, - ).eq(0.5); - expect( - stateVariables["/_award2"].state.fractionSatisfied.value, - ).eq(1); - }); - - cy.log("click submit"); - - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputPartialAnchor).should("have.text", "50 %"); - - cy.get(cesc("#\\/cr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2βˆ’2xβˆ’3"); - }); - cy.get(cesc("#\\/sr") + " .mjx-mrow").should( - "contain.text", - "x2βˆ’2xβˆ’3", - ); - - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2βˆ’2xβˆ’3"); - }); - cy.get(cesc("#\\/ca")).should("have.text", "0.5"); - - cy.log( - "check that no longer have getters for creditAchievedIfSubmit/fractionSatisfiedIfSubmit", - ); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let stateVarObj = - stateVariables["/_award1"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - stateVarObj = - stateVariables["/_award1"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - stateVarObj = - stateVariables["/_award2"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - stateVarObj = - stateVariables["/_award2"].state.fractionSatisfiedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - stateVarObj = - stateVariables["/ans"].state.creditAchievedIfSubmit; - expect( - Boolean( - Object.getOwnPropertyDescriptor(stateVarObj, "value") - .get || stateVarObj.immutable, - ), - ).to.be.false; - - expect( - stateVariables["/_award1"].state.creditAchievedIfSubmit - .value, - ).eq(0); - expect( - stateVariables["/_award1"].state.fractionSatisfiedIfSubmit - .value, - ).eq(0); - expect( - stateVariables["/_award1"].state.creditAchieved.value, - ).eq(0); - expect( - stateVariables["/_award1"].state.fractionSatisfied.value, - ).eq(0); - expect( - stateVariables["/_award2"].state.creditAchievedIfSubmit - .value, - ).eq(0.5); - expect( - stateVariables["/_award2"].state.fractionSatisfiedIfSubmit - .value, - ).eq(1); - expect( - stateVariables["/_award2"].state.creditAchieved.value, - ).eq(0.5); - expect( - stateVariables["/_award2"].state.fractionSatisfied.value, - ).eq(1); - expect( - stateVariables["/ans"].state.creditAchievedIfSubmit.value, - ).eq(0.5); - expect(stateVariables["/ans"].state.creditAchieved.value).eq( - 0.5, - ); - }); - }); - }); - - it("verify tab behavior, math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - let mathinputCorrectAnchor = cesc2( - "#" + mathinputName + "_correct", + // the 2nd and 4th input should be disabled, + // but this isn't working yet. + // For now, best we can do is make sure button still say incorrect + cy.get(cesc2("#" + inputNames[0]) + " textarea").type( + "{end}{backspace}y", + { force: true }, ); - let mathinputIncorrectAnchor = cesc2( - "#" + mathinputName + "_incorrect", + cy.get(cesc2("#" + inputNames[1]) + " textarea").type( + "{end}{backspace}y", + { force: true }, ); - - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - - cy.log("Type correct answer in"); - 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.log("Press tab"); - cy.get(mathinputSubmitAnchor).focus(); - cy.get(mathinputAnchor).tab(); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(mathinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - }); - }); - - it("verify tab behavior, text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - hello - `, - }, - "*", + cy.get(cesc2("#" + inputNames[2]) + " textarea").type( + "{end}{backspace}y", + { force: true }, ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let textinputName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let textinputAnchor = cesc2("#" + textinputName) + "_input"; - let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); - let textinputCorrectAnchor = cesc2( - "#" + textinputName + "_correct", + cy.get(cesc2("#" + inputNames[3]) + " textarea").type( + "{end}{backspace}y", + { force: true }, ); - let textinputIncorrectAnchor = cesc2( - "#" + textinputName + "_incorrect", + cy.get(cesc2("#" + inputNames[0]) + "_submit").click(); + cy.get(cesc2("#/_answer3_submit")).click(); + cy.get(cesc2("#" + inputNames[0]) + "_incorrect").should( + "be.visible", ); - - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - - cy.log("Type correct answer in"); - cy.get(textinputAnchor).type(`hello`); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - - cy.log("Press tab"); - cy.get(textinputAnchor).tab(); - cy.get(textinputSubmitAnchor).should("be.visible"); - cy.get(textinputCorrectAnchor).should("not.exist"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - - cy.log("Press enter on submit button"); - cy.get(textinputSubmitAnchor).type(`{enter}`, { force: true }); - cy.get(textinputSubmitAnchor).should("not.exist"); - cy.get(textinputCorrectAnchor).should("be.visible"); - cy.get(textinputIncorrectAnchor).should("not.exist"); - }); - }); - - it("submit label", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

x

-

x

-

x

-

x

- `, - }, - "*", + cy.get(cesc2("#" + inputNames[1]) + "_correct").should( + "be.visible", ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mathinput1Name = - stateVariables["/ans1"].stateValues.inputChildren[0] - .componentName; - let mathinput1Anchor = cesc2("#" + mathinput1Name) + " textarea"; - - let mathinput2Name = - stateVariables["/ans2"].stateValues.inputChildren[0] - .componentName; - let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - - let mathinput3Name = - stateVariables["/ans3"].stateValues.inputChildren[0] - .componentName; - let mathinput3Anchor = cesc2("#" + mathinput3Name) + " textarea"; - - let mathinput4Name = - stateVariables["/ans4"].stateValues.inputChildren[0] - .componentName; - let mathinput4Anchor = cesc2("#" + mathinput4Name) + " textarea"; - - cy.get(cesc("#\\/ans1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Check Work"); - }); - cy.get(cesc("#\\/ans2_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Hit it!"); - }); - cy.get(cesc("#\\/ans3_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Check Work"); - }); - cy.get(cesc("#\\/ans4_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Hit it!"); - }); - - cy.get(mathinput1Anchor).type("x{enter}", { force: true }); - cy.get(mathinput2Anchor).type("x{enter}", { force: true }); - cy.get(mathinput3Anchor).type("x{enter}", { force: true }); - cy.get(mathinput4Anchor).type("x{enter}", { force: true }); - - cy.get(cesc("#\\/ans1_submit")).click(); - cy.get(cesc("#\\/ans2_submit")).click(); - cy.get(cesc("#\\/ans3_submit")).click(); - cy.get(cesc("#\\/ans4_submit")).click(); - - cy.get(cesc("#\\/ans1_correct")).should("contain.text", "Correct"); - cy.get(cesc("#\\/ans2_correct")).should("contain.text", "Correct"); - cy.get(cesc("#\\/ans3_correct")).should("contain.text", "Correct"); - cy.get(cesc("#\\/ans4_correct")).should("contain.text", "Correct"); - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_showCorrectness").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); + cy.get(cesc2("#/_answer3_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer4_correct")).should("be.visible"); - cy.get(cesc("#\\/ans1_submit")).should( - "contain.text", - "Submit Response", + cy.get(cesc2("#" + inputNames[4]) + "_input") + .clear() + .type("bye"); + cy.get(cesc2("#" + inputNames[5]) + "_input").should("be.disabled"); + cy.get(cesc2("#" + inputNames[6]) + "_input") + .clear() + .type("bye"); + cy.get(cesc2("#" + inputNames[7]) + "_input").should("be.disabled"); + cy.get(cesc2("#" + inputNames[4]) + "_submit").click(); + cy.get(cesc2("#/_answer7_submit")).click(); + cy.get(cesc2("#" + inputNames[4]) + "_incorrect").should( + "be.visible", ); - cy.get(cesc("#\\/ans2_submit")).should( - "contain.text", - "Submit Response", + cy.get(cesc2("#" + inputNames[5]) + "_correct").should( + "be.visible", ); - cy.get(cesc("#\\/ans3_submit")).should("contain.text", "Guess"); - cy.get(cesc("#\\/ans4_submit")).should("contain.text", "Guess"); - - cy.get(cesc("#\\/ans1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Submit Response"); - }); - cy.get(cesc("#\\/ans2_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Submit Response"); - }); - cy.get(cesc("#\\/ans3_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Guess"); - }); - cy.get(cesc("#\\/ans4_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Guess"); - }); + cy.get(cesc2("#/_answer7_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer8_correct")).should("be.visible"); - cy.get(mathinput1Anchor).type("x{enter}", { force: true }); - cy.get(mathinput2Anchor).type("x{enter}", { force: true }); - cy.get(mathinput3Anchor).type("x{enter}", { force: true }); - cy.get(mathinput4Anchor).type("x{enter}", { force: true }); + cy.get(cesc2("#/_choiceinput1")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput2")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput3")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput4")) + .contains("no") + .click({ force: true }); + cy.get(cesc2("#/_choiceinput1_submit")).click(); + cy.get(cesc2("#/_answer11_submit")).click(); + cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); + cy.get(cesc2("#/_choiceinput2_correct")).should("be.visible"); + cy.get(cesc2("#/_answer11_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer12_correct")).should("be.visible"); - cy.get(cesc("#\\/ans1_submit")).click(); - cy.get(cesc("#\\/ans2_submit")).click(); - cy.get(cesc("#\\/ans3_submit")).click(); - cy.get(cesc("#\\/ans4_submit")).click(); + cy.get(cesc("#\\/_choiceinput5")).select(`no`); + cy.get(cesc("#\\/_choiceinput6")).should("be.disabled"); + cy.get(cesc("#\\/_choiceinput7")).select(`no`); + cy.get(cesc("#\\/_choiceinput8")).should("be.disabled"); + cy.get(cesc2("#/_choiceinput5_submit")).click(); + cy.get(cesc2("#/_answer15_submit")).click(); + cy.get(cesc2("#/_choiceinput5_incorrect")).should("be.visible"); + cy.get(cesc2("#/_choiceinput6_correct")).should("be.visible"); + cy.get(cesc2("#/_answer15_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer16_correct")).should("be.visible"); - cy.get(cesc("#\\/ans1_saved")).should( - "contain.text", - "Response Saved", + cy.get(cesc2("#" + inputNames[16])).click(); + cy.get(cesc2("#" + inputNames[17]) + "_input").should( + "be.disabled", ); - cy.get(cesc("#\\/ans2_saved")).should( - "contain.text", - "Response Saved", + cy.get(cesc2("#" + inputNames[18])).click(); + cy.get(cesc2("#" + inputNames[19]) + "_input").should( + "be.disabled", ); - cy.get(cesc("#\\/ans3_saved")).should( - "contain.text", - "Response Saved", + cy.get(cesc2("#" + inputNames[16]) + "_submit").click(); + cy.get(cesc2("#/_answer19_submit")).click(); + cy.get(cesc2("#" + inputNames[16]) + "_incorrect").should( + "be.visible", ); - cy.get(cesc("#\\/ans4_saved")).should( - "contain.text", - "Response Saved", + cy.get(cesc2("#" + inputNames[17]) + "_correct").should( + "be.visible", ); + cy.get(cesc2("#/_answer19_incorrect")).should("be.visible"); + cy.get(cesc2("#/_answer20_correct")).should("be.visible"); }); }); - it("submit label, choiceinput", () => { + it("disable after correct, depends on external", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

-

- - yes - no - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Check Work"); - }); - cy.get(cesc("#\\/_choiceinput2_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Hit it!"); - }); - cy.get(cesc("#\\/_choiceinput3_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Check Work"); - }); - cy.get(cesc("#\\/_choiceinput4_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Hit it!"); - }); - - cy.get(cesc("#\\/_choiceinput1")) - .contains(`yes`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput2")) - .contains(`yes`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput3")) - .contains(`yes`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput4")) - .contains(`yes`) - .click({ force: true }); - - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput2_submit")).click(); - cy.get(cesc("#\\/_choiceinput3_submit")).click(); - cy.get(cesc("#\\/_choiceinput4_submit")).click(); - - cy.get(cesc("#\\/_choiceinput1_correct")).should( - "contain.text", - "Correct", - ); - cy.get(cesc("#\\/_choiceinput2_correct")).should( - "contain.text", - "Correct", - ); - cy.get(cesc("#\\/_choiceinput3_correct")).should( - "contain.text", - "Correct", - ); - cy.get(cesc("#\\/_choiceinput4_correct")).should( - "contain.text", - "Correct", - ); - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_showCorrectness").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - cy.get(cesc("#\\/_choiceinput1_submit")).should( - "contain.text", - "Submit Response", - ); - cy.get(cesc("#\\/_choiceinput2_submit")).should( - "contain.text", - "Submit Response", - ); - cy.get(cesc("#\\/_choiceinput3_submit")).should( - "contain.text", - "Guess", - ); - cy.get(cesc("#\\/_choiceinput4_submit")).should( - "contain.text", - "Guess", - ); - - cy.get(cesc("#\\/_choiceinput1_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Submit Response"); - }); - cy.get(cesc("#\\/_choiceinput2_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Submit Response"); - }); - cy.get(cesc("#\\/_choiceinput3_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Guess"); - }); - cy.get(cesc("#\\/_choiceinput4_submit")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Guess"); - }); - - cy.get(cesc("#\\/_choiceinput1")) - .contains(`yes`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput2")) - .contains(`yes`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput3")) - .contains(`yes`) - .click({ force: true }); - cy.get(cesc("#\\/_choiceinput4")) - .contains(`yes`) - .click({ force: true }); - - cy.get(cesc("#\\/_choiceinput1_submit")).click(); - cy.get(cesc("#\\/_choiceinput2_submit")).click(); - cy.get(cesc("#\\/_choiceinput3_submit")).click(); - cy.get(cesc("#\\/_choiceinput4_submit")).click(); - - cy.get(cesc("#\\/_choiceinput1_saved")).should( - "contain.text", - "Response Saved", - ); - cy.get(cesc("#\\/_choiceinput2_saved")).should( - "contain.text", - "Response Saved", - ); - cy.get(cesc("#\\/_choiceinput3_saved")).should( - "contain.text", - "Response Saved", - ); - cy.get(cesc("#\\/_choiceinput4_saved")).should( - "contain.text", - "Response Saved", - ); - }); - it("short award and full award combined", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - + + + (3,4) + (-5,6) + + - - x^2 - - $P.x > 0 + +

Move point to (3,4):

+

+ + $A = (3,4) + +

+

+ + $A = (3,4) + +

+ +

Move point to (-5,6):

+

+ + $A = (-5,6) - -

Submitted responses: $_answer1.submittedResponses{assignNames="sr1 sr2"}

- `, +

+

+ + $A = (-5,6) + +

+ +

+ +

Enter x in above blank.

+

+ $mi=x +

+

+ $mi=x +

+ +

Enter y in above blank.

+

+ $mi=y +

+

+ $mi=y +

+ + `, }, "*", ); @@ -31970,106 +2494,83 @@ describe("Answer Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/_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", - ); - let mathinputPartialAnchor = cesc2( - "#" + mathinputName + "_partial", - ); - - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - - cy.log("Correct answer in mathinput"); - cy.get(mathinputAnchor).type(`x^2{enter}`, { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("have.text", "60 %"); - - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0"); - }); + cy.log("Submit incorrect answers"); + for (let i = 1; i <= 8; i++) { + cy.get(cesc(`#\\/_answer${i}_submit`)).click(); + cy.get(cesc(`#\\/_answer${i}_incorrect`)).should("be.visible"); + } - cy.log("Correct point location"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 2, y: -7 }, - }); + cy.log("submit first correct answers"); + cy.window().then(async (win) => { + await win.callAction1({ + actionName: "movePoint", + componentName: "/A", + args: { x: 3, y: 4 }, }); - cy.get(mathinputSubmitAnchor).click(); + }); + cy.get(cesc("#\\/mi") + " textarea").type("x{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); + for (let i = 1; i <= 8; i++) { + cy.get(cesc(`#\\/_answer${i}_submit`)).click(); + if (i % 4 === 1 || i % 4 == 2) { + cy.get(cesc(`#\\/_answer${i}_correct`)).should("be.visible"); + } else { + cy.get(cesc(`#\\/_answer${i}_incorrect`)).should("be.visible"); + } + } - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("2"); - }); + cy.log("submit second correct answers"); + cy.window().then(async (win) => { + await win.callAction1({ + actionName: "movePoint", + componentName: "/A", + args: { x: -5, y: 6 }, + }); + }); + cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}y{enter}", { + force: true, + }); - cy.log("Incorrect answer in mathinput"); - cy.get(mathinputAnchor).type(`{end}y{enter}`, { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("have.text", "40 %"); + for (let i = 1; i <= 8; i++) { + if (i % 4 !== 2) { + cy.get(cesc(`#\\/_answer${i}_submit`)).click(); + } + if (i % 4 === 1) { + cy.get(cesc(`#\\/_answer${i}_incorrect`)).should("be.visible"); + } else { + cy.get(cesc(`#\\/_answer${i}_correct`)).should("be.visible"); + } + } - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x2y"); - }); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("2"); - }); + cy.log("submit second incorrect answers"); + cy.window().then(async (win) => { + await win.callAction1({ + actionName: "movePoint", + componentName: "/A", + args: { x: 1, y: -1 }, + }); + }); + cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}z{enter}", { + force: true, }); + + for (let i = 1; i <= 8; i++) { + if (i % 4 === 2 || i % 4 === 0) { + cy.get(cesc(`#\\/_answer${i}_correct`)).should("be.visible"); + } else { + cy.get(cesc(`#\\/_answer${i}_submit`)).click(); + cy.get(cesc(`#\\/_answer${i}_incorrect`)).should("be.visible"); + } + } }); - it("derivative works without award", () => { + it("verify tab behavior, math", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

What is the derivative of x^2? - $f

-

Submitted response:

+ x `, }, "*", @@ -32096,61 +2597,34 @@ describe("Answer Tag Tests", function () { cy.get(mathinputCorrectAnchor).should("not.exist"); cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("\uff3f"); - }); - cy.log("Correct answer in mathinput"); - cy.get(mathinputAnchor).type(`2x{enter}`, { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.log("Type correct answer in"); + 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(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("2x"); - }); - - cy.log("Incorrect answer in mathinput"); - cy.get(mathinputAnchor).type(`{end}x/2{enter}`, { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.log("Press tab"); + cy.get(mathinputSubmitAnchor).focus(); + cy.get(mathinputAnchor).tab(); + cy.get(mathinputSubmitAnchor).should("be.visible"); cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(cesc("#\\/sr") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("2xx2"); - }); + cy.log("Press enter on submit button"); + cy.get(mathinputSubmitAnchor).type(`{enter}`, { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); }); }); - it("case-insensitive match, math", () => { + it("verify tab behavior, text", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

Default, sugar: x+Y

-

Case-insensitive, sugar: x+Y

-

Partial credit for insensitive, shortcut award: - - x+Y - x+Y - -

-

Partial credit for insensitive, full syntax: - - - $fullmi = x+Y - $fullmi = x+Y - -

+ hello `, }, "*", @@ -32161,266 +2635,52 @@ describe("Answer Tag Tests", function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let mathinputDefSugarName = - stateVariables["/defSugar"].stateValues.inputChildren[0] - .componentName; - let mathinputDefSugarAnchor = - cesc2("#" + mathinputDefSugarName) + " textarea"; - let mathinputDefSugarSubmitAnchor = cesc2( - "#" + mathinputDefSugarName + "_submit", - ); - let mathinputDefSugarCorrectAnchor = cesc2( - "#" + mathinputDefSugarName + "_correct", - ); - let mathinputDefSugarIncorrectAnchor = cesc2( - "#" + mathinputDefSugarName + "_incorrect", - ); - let mathinputInsSugarName = - stateVariables["/insSugar"].stateValues.inputChildren[0] - .componentName; - let mathinputInsSugarAnchor = - cesc2("#" + mathinputInsSugarName) + " textarea"; - let mathinputInsSugarSubmitAnchor = cesc2( - "#" + mathinputInsSugarName + "_submit", - ); - let mathinputInsSugarCorrectAnchor = cesc2( - "#" + mathinputInsSugarName + "_correct", - ); - let mathinputInsSugarIncorrectAnchor = cesc2( - "#" + mathinputInsSugarName + "_incorrect", - ); - let mathinputAwardName = - stateVariables["/shortAwards"].stateValues.inputChildren[0] + let textinputName = + stateVariables["/_answer1"].stateValues.inputChildren[0] .componentName; - let mathinputAwardAnchor = - cesc2("#" + mathinputAwardName) + " textarea"; - let mathinputAwardSubmitAnchor = cesc2( - "#" + mathinputAwardName + "_submit", - ); - let mathinputAwardCorrectAnchor = cesc2( - "#" + mathinputAwardName + "_correct", - ); - let mathinputAwardIncorrectAnchor = cesc2( - "#" + mathinputAwardName + "_incorrect", - ); - let mathinputAwardPartialAnchor = cesc2( - "#" + mathinputAwardName + "_partial", - ); - let mathinputFullName = "/fullmi"; - let mathinputFullAnchor = - cesc2("#" + mathinputFullName) + " textarea"; - let mathinputFullSubmitAnchor = cesc2( - "#" + mathinputFullName + "_submit", - ); - let mathinputFullCorrectAnchor = cesc2( - "#" + mathinputFullName + "_correct", - ); - let mathinputFullIncorrectAnchor = cesc2( - "#" + mathinputFullName + "_incorrect", - ); - let mathinputFullPartialAnchor = cesc2( - "#" + mathinputFullName + "_partial", - ); - - cy.get(mathinputDefSugarSubmitAnchor).should("be.visible"); - cy.get(mathinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputDefSugarIncorrectAnchor).should("not.exist"); - cy.get(mathinputInsSugarSubmitAnchor).should("be.visible"); - cy.get(mathinputInsSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputInsSugarIncorrectAnchor).should("not.exist"); - cy.get(mathinputAwardSubmitAnchor).should("be.visible"); - cy.get(mathinputAwardCorrectAnchor).should("not.exist"); - cy.get(mathinputAwardIncorrectAnchor).should("not.exist"); - cy.get(mathinputAwardPartialAnchor).should("not.exist"); - cy.get(mathinputFullSubmitAnchor).should("be.visible"); - cy.get(mathinputFullCorrectAnchor).should("not.exist"); - cy.get(mathinputFullIncorrectAnchor).should("not.exist"); - cy.get(mathinputFullPartialAnchor).should("not.exist"); - - cy.log("wrong case 1"); - cy.get(mathinputDefSugarAnchor).type(`x+y{enter}`, { force: true }); - cy.get(mathinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(mathinputInsSugarAnchor).type(`x+y{enter}`, { force: true }); - cy.get(mathinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputInsSugarCorrectAnchor).should("be.visible"); - cy.get(mathinputInsSugarIncorrectAnchor).should("not.exist"); - - cy.get(mathinputAwardAnchor).type(`x+y{enter}`, { force: true }); - cy.get(mathinputAwardSubmitAnchor).should("not.exist"); - cy.get(mathinputAwardCorrectAnchor).should("not.exist"); - cy.get(mathinputAwardIncorrectAnchor).should("not.exist"); - cy.get(mathinputAwardPartialAnchor).should("have.text", "50 %"); - - cy.get(mathinputFullAnchor).type(`x+y{enter}`, { force: true }); - cy.get(mathinputFullSubmitAnchor).should("not.exist"); - cy.get(mathinputFullCorrectAnchor).should("not.exist"); - cy.get(mathinputFullIncorrectAnchor).should("not.exist"); - cy.get(mathinputFullPartialAnchor).should("have.text", "50 %"); - - cy.log("correct case"); - cy.get(mathinputDefSugarAnchor).type( - `{end}{backspace}{backspace}{backspace}x+Y{enter}`, - { force: true }, - ); - cy.get(mathinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputDefSugarCorrectAnchor).should("be.visible"); - cy.get(mathinputDefSugarIncorrectAnchor).should("not.exist"); - - cy.get(mathinputInsSugarAnchor).type( - `{end}{backspace}{backspace}{backspace}x+Y{enter}`, - { force: true }, - ); - cy.get(mathinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputInsSugarCorrectAnchor).should("be.visible"); - cy.get(mathinputInsSugarIncorrectAnchor).should("not.exist"); - - cy.get(mathinputAwardAnchor).type( - `{end}{backspace}{backspace}{backspace}x+Y{enter}`, - { force: true }, - ); - cy.get(mathinputAwardSubmitAnchor).should("not.exist"); - cy.get(mathinputAwardCorrectAnchor).should("be.visible"); - cy.get(mathinputAwardIncorrectAnchor).should("not.exist"); - cy.get(mathinputAwardPartialAnchor).should("not.exist"); - - cy.get(mathinputFullAnchor).type( - `{end}{backspace}{backspace}{backspace}x+Y{enter}`, - { force: true }, - ); - cy.get(mathinputFullSubmitAnchor).should("not.exist"); - cy.get(mathinputFullCorrectAnchor).should("be.visible"); - cy.get(mathinputFullIncorrectAnchor).should("not.exist"); - cy.get(mathinputFullPartialAnchor).should("not.exist"); - - cy.log("wrong case 2"); - cy.get(mathinputDefSugarAnchor).type( - `{end}{backspace}{backspace}{backspace}X+Y{enter}`, - { force: true }, - ); - cy.get(mathinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(mathinputInsSugarAnchor).type( - `{end}{backspace}{backspace}{backspace}X+Y{enter}`, - { force: true }, - ); - cy.get(mathinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputInsSugarCorrectAnchor).should("be.visible"); - cy.get(mathinputInsSugarIncorrectAnchor).should("not.exist"); - - cy.get(mathinputAwardAnchor).type( - `{end}{backspace}{backspace}{backspace}X+Y{enter}`, - { force: true }, - ); - cy.get(mathinputAwardSubmitAnchor).should("not.exist"); - cy.get(mathinputAwardCorrectAnchor).should("not.exist"); - cy.get(mathinputAwardIncorrectAnchor).should("not.exist"); - cy.get(mathinputAwardPartialAnchor).should("have.text", "50 %"); - - cy.get(mathinputFullAnchor).type( - `{end}{backspace}{backspace}{backspace}X+Y{enter}`, - { force: true }, - ); - cy.get(mathinputFullSubmitAnchor).should("not.exist"); - cy.get(mathinputFullCorrectAnchor).should("not.exist"); - cy.get(mathinputFullIncorrectAnchor).should("not.exist"); - cy.get(mathinputFullPartialAnchor).should("have.text", "50 %"); - - cy.log("incorrect answer"); - cy.get(mathinputDefSugarAnchor).type( - `{end}{backspace}{backspace}{enter}`, - { force: true }, - ); - cy.get(mathinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(mathinputInsSugarAnchor).type( - `{end}{backspace}{backspace}{enter}`, - { force: true }, + let textinputAnchor = cesc2("#" + textinputName) + "_input"; + let textinputSubmitAnchor = cesc2("#" + textinputName + "_submit"); + let textinputCorrectAnchor = cesc2( + "#" + textinputName + "_correct", ); - cy.get(mathinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputInsSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputInsSugarIncorrectAnchor).should("be.visible"); - - cy.get(mathinputAwardAnchor).type( - `{end}{backspace}{backspace}{enter}`, - { - force: true, - }, + let textinputIncorrectAnchor = cesc2( + "#" + textinputName + "_incorrect", ); - cy.get(mathinputAwardSubmitAnchor).should("not.exist"); - cy.get(mathinputAwardCorrectAnchor).should("not.exist"); - cy.get(mathinputAwardIncorrectAnchor).should("be.visible"); - cy.get(mathinputAwardPartialAnchor).should("not.exist"); - cy.get(mathinputFullAnchor).type( - `{end}{backspace}{backspace}{enter}`, - { - force: true, - }, - ); - cy.get(mathinputFullSubmitAnchor).should("not.exist"); - cy.get(mathinputFullCorrectAnchor).should("not.exist"); - cy.get(mathinputFullIncorrectAnchor).should("be.visible"); - cy.get(mathinputFullPartialAnchor).should("not.exist"); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.log("wrong case 3"); - cy.get(mathinputDefSugarAnchor).type(`{end}+y{enter}`, { - force: true, - }); - cy.get(mathinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputDefSugarIncorrectAnchor).should("be.visible"); + cy.log("Type correct answer in"); + cy.get(textinputAnchor).type(`hello`); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputInsSugarAnchor).type(`{end}+y{enter}`, { - force: true, - }); - cy.get(mathinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputInsSugarCorrectAnchor).should("be.visible"); - cy.get(mathinputInsSugarIncorrectAnchor).should("not.exist"); + cy.log("Press tab"); + cy.get(textinputAnchor).tab(); + cy.get(textinputSubmitAnchor).should("be.visible"); + cy.get(textinputCorrectAnchor).should("not.exist"); + cy.get(textinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputAwardAnchor).type(`{end}+y{enter}`, { - force: true, - }); - cy.get(mathinputAwardSubmitAnchor).should("not.exist"); - cy.get(mathinputAwardCorrectAnchor).should("not.exist"); - cy.get(mathinputAwardIncorrectAnchor).should("not.exist"); - cy.get(mathinputAwardPartialAnchor).should("have.text", "50 %"); - - cy.get(mathinputFullAnchor).type(`{end}+y{enter}`, { force: true }); - cy.get(mathinputFullSubmitAnchor).should("not.exist"); - cy.get(mathinputFullCorrectAnchor).should("not.exist"); - cy.get(mathinputFullIncorrectAnchor).should("not.exist"); - cy.get(mathinputFullPartialAnchor).should("have.text", "50 %"); + cy.log("Press enter on submit button"); + cy.get(textinputSubmitAnchor).type(`{enter}`, { force: true }); + cy.get(textinputSubmitAnchor).should("not.exist"); + cy.get(textinputCorrectAnchor).should("be.visible"); + cy.get(textinputIncorrectAnchor).should("not.exist"); }); }); - it("case-insensitive match, text", () => { + it("submit label", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

Default, sugar: Hello there!

-

Case-insensitive, sugar: Hello there!

-

Partial credit for insensitive, shortcut award: - - Hello there! - Hello there! - -

-

Partial credit for insensitive, full syntax: - - - $fullmi = Hello there! - $fullmi = Hello there! - -

+

x

+

x

+

x

+

x

`, }, "*", @@ -32431,224 +2691,159 @@ describe("Answer Tag Tests", function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let textinputDefSugarName = - stateVariables["/defSugar"].stateValues.inputChildren[0] + + let mathinput1Name = + stateVariables["/ans1"].stateValues.inputChildren[0] .componentName; - let textinputDefSugarAnchor = - cesc2("#" + textinputDefSugarName) + "_input"; - let textinputDefSugarSubmitAnchor = cesc2( - "#" + textinputDefSugarName + "_submit", - ); - let textinputDefSugarCorrectAnchor = cesc2( - "#" + textinputDefSugarName + "_correct", - ); - let textinputDefSugarIncorrectAnchor = cesc2( - "#" + textinputDefSugarName + "_incorrect", - ); - let textinputInsSugarName = - stateVariables["/insSugar"].stateValues.inputChildren[0] + let mathinput1Anchor = cesc2("#" + mathinput1Name) + " textarea"; + + let mathinput2Name = + stateVariables["/ans2"].stateValues.inputChildren[0] .componentName; - let textinputInsSugarAnchor = - cesc2("#" + textinputInsSugarName) + "_input"; - let textinputInsSugarSubmitAnchor = cesc2( - "#" + textinputInsSugarName + "_submit", - ); - let textinputInsSugarCorrectAnchor = cesc2( - "#" + textinputInsSugarName + "_correct", - ); - let textinputInsSugarIncorrectAnchor = cesc2( - "#" + textinputInsSugarName + "_incorrect", - ); - let textinputAwardName = - stateVariables["/shortAwards"].stateValues.inputChildren[0] + let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; + + let mathinput3Name = + stateVariables["/ans3"].stateValues.inputChildren[0] .componentName; - let textinputAwardAnchor = - cesc2("#" + textinputAwardName) + "_input"; - let textinputAwardSubmitAnchor = cesc2( - "#" + textinputAwardName + "_submit", - ); - let textinputAwardCorrectAnchor = cesc2( - "#" + textinputAwardName + "_correct", - ); - let textinputAwardIncorrectAnchor = cesc2( - "#" + textinputAwardName + "_incorrect", + let mathinput3Anchor = cesc2("#" + mathinput3Name) + " textarea"; + + let mathinput4Name = + stateVariables["/ans4"].stateValues.inputChildren[0] + .componentName; + let mathinput4Anchor = cesc2("#" + mathinput4Name) + " textarea"; + + cy.get(cesc("#\\/ans1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Check Work"); + }); + cy.get(cesc("#\\/ans2_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Hit it!"); + }); + cy.get(cesc("#\\/ans3_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Check Work"); + }); + cy.get(cesc("#\\/ans4_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Hit it!"); + }); + + cy.get(mathinput1Anchor).type("x{enter}", { force: true }); + cy.get(mathinput2Anchor).type("x{enter}", { force: true }); + cy.get(mathinput3Anchor).type("x{enter}", { force: true }); + cy.get(mathinput4Anchor).type("x{enter}", { force: true }); + + cy.get(cesc("#\\/ans1_submit")).click(); + cy.get(cesc("#\\/ans2_submit")).click(); + cy.get(cesc("#\\/ans3_submit")).click(); + cy.get(cesc("#\\/ans4_submit")).click(); + + cy.get(cesc("#\\/ans1_correct")).should("contain.text", "Correct"); + cy.get(cesc("#\\/ans2_correct")).should("contain.text", "Correct"); + cy.get(cesc("#\\/ans3_correct")).should("contain.text", "Correct"); + cy.get(cesc("#\\/ans4_correct")).should("contain.text", "Correct"); + + cy.get("#testRunner_toggleControls").click(); + cy.get("#testRunner_showCorrectness").click(); + cy.wait(100); + cy.get("#testRunner_toggleControls").click(); + + cy.get(cesc("#\\/ans1_submit")).should( + "contain.text", + "Submit Response", ); - let textinputAwardPartialAnchor = cesc2( - "#" + textinputAwardName + "_partial", + cy.get(cesc("#\\/ans2_submit")).should( + "contain.text", + "Submit Response", ); - let textinputFullName = "/fullmi"; - let textinputFullAnchor = cesc2("#" + textinputFullName) + "_input"; - let textinputFullSubmitAnchor = cesc2( - "#" + textinputFullName + "_submit", + cy.get(cesc("#\\/ans3_submit")).should("contain.text", "Guess"); + cy.get(cesc("#\\/ans4_submit")).should("contain.text", "Guess"); + + cy.get(cesc("#\\/ans1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Submit Response"); + }); + cy.get(cesc("#\\/ans2_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Submit Response"); + }); + cy.get(cesc("#\\/ans3_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Guess"); + }); + cy.get(cesc("#\\/ans4_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Guess"); + }); + + cy.get(mathinput1Anchor).type("x{enter}", { force: true }); + cy.get(mathinput2Anchor).type("x{enter}", { force: true }); + cy.get(mathinput3Anchor).type("x{enter}", { force: true }); + cy.get(mathinput4Anchor).type("x{enter}", { force: true }); + + cy.get(cesc("#\\/ans1_submit")).click(); + cy.get(cesc("#\\/ans2_submit")).click(); + cy.get(cesc("#\\/ans3_submit")).click(); + cy.get(cesc("#\\/ans4_submit")).click(); + + cy.get(cesc("#\\/ans1_saved")).should( + "contain.text", + "Response Saved", ); - let textinputFullCorrectAnchor = cesc2( - "#" + textinputFullName + "_correct", + cy.get(cesc("#\\/ans2_saved")).should( + "contain.text", + "Response Saved", ); - let textinputFullIncorrectAnchor = cesc2( - "#" + textinputFullName + "_incorrect", + cy.get(cesc("#\\/ans3_saved")).should( + "contain.text", + "Response Saved", ); - let textinputFullPartialAnchor = cesc2( - "#" + textinputFullName + "_partial", + cy.get(cesc("#\\/ans4_saved")).should( + "contain.text", + "Response Saved", ); - - cy.get(textinputDefSugarSubmitAnchor).should("be.visible"); - cy.get(textinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(textinputDefSugarIncorrectAnchor).should("not.exist"); - cy.get(textinputInsSugarSubmitAnchor).should("be.visible"); - cy.get(textinputInsSugarCorrectAnchor).should("not.exist"); - cy.get(textinputInsSugarIncorrectAnchor).should("not.exist"); - cy.get(textinputAwardSubmitAnchor).should("be.visible"); - cy.get(textinputAwardCorrectAnchor).should("not.exist"); - cy.get(textinputAwardIncorrectAnchor).should("not.exist"); - cy.get(textinputAwardPartialAnchor).should("not.exist"); - cy.get(textinputFullSubmitAnchor).should("be.visible"); - cy.get(textinputFullCorrectAnchor).should("not.exist"); - cy.get(textinputFullIncorrectAnchor).should("not.exist"); - cy.get(textinputFullPartialAnchor).should("not.exist"); - - cy.log("wrong case 1"); - cy.get(textinputDefSugarAnchor).type(`hello there!{enter}`); - cy.get(textinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(textinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(textinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(textinputInsSugarAnchor).type(`hello there!{enter}`); - cy.get(textinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(textinputInsSugarCorrectAnchor).should("be.visible"); - cy.get(textinputInsSugarIncorrectAnchor).should("not.exist"); - - cy.get(textinputAwardAnchor).type(`hello there!{enter}`); - cy.get(textinputAwardSubmitAnchor).should("not.exist"); - cy.get(textinputAwardCorrectAnchor).should("not.exist"); - cy.get(textinputAwardIncorrectAnchor).should("not.exist"); - cy.get(textinputAwardPartialAnchor).should("have.text", "50 %"); - - cy.get(textinputFullAnchor).type(`hello there!{enter}`); - cy.get(textinputFullSubmitAnchor).should("not.exist"); - cy.get(textinputFullCorrectAnchor).should("not.exist"); - cy.get(textinputFullIncorrectAnchor).should("not.exist"); - cy.get(textinputFullPartialAnchor).should("have.text", "50 %"); - - cy.log("correct case"); - cy.get(textinputDefSugarAnchor).clear().type(`Hello there!{enter}`); - cy.get(textinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(textinputDefSugarCorrectAnchor).should("be.visible"); - cy.get(textinputDefSugarIncorrectAnchor).should("not.exist"); - - cy.get(textinputInsSugarAnchor).clear().type(`Hello there!{enter}`); - cy.get(textinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(textinputInsSugarCorrectAnchor).should("be.visible"); - cy.get(textinputInsSugarIncorrectAnchor).should("not.exist"); - - cy.get(textinputAwardAnchor).clear().type(`Hello there!{enter}`); - cy.get(textinputAwardSubmitAnchor).should("not.exist"); - cy.get(textinputAwardCorrectAnchor).should("be.visible"); - cy.get(textinputAwardIncorrectAnchor).should("not.exist"); - cy.get(textinputAwardPartialAnchor).should("not.exist"); - - cy.get(textinputFullAnchor).clear().type(`Hello there!{enter}`); - cy.get(textinputFullSubmitAnchor).should("not.exist"); - cy.get(textinputFullCorrectAnchor).should("be.visible"); - cy.get(textinputFullIncorrectAnchor).should("not.exist"); - cy.get(textinputFullPartialAnchor).should("not.exist"); - - cy.log("wrong case 2"); - cy.get(textinputDefSugarAnchor).clear().type(`Hello There!{enter}`); - cy.get(textinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(textinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(textinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(textinputInsSugarAnchor).clear().type(`Hello There!{enter}`); - cy.get(textinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(textinputInsSugarCorrectAnchor).should("be.visible"); - cy.get(textinputInsSugarIncorrectAnchor).should("not.exist"); - - cy.get(textinputAwardAnchor).clear().type(`Hello There!{enter}`); - cy.get(textinputAwardSubmitAnchor).should("not.exist"); - cy.get(textinputAwardCorrectAnchor).should("not.exist"); - cy.get(textinputAwardIncorrectAnchor).should("not.exist"); - cy.get(textinputAwardPartialAnchor).should("have.text", "50 %"); - - cy.get(textinputFullAnchor).clear().type(`Hello There!{enter}`); - cy.get(textinputFullSubmitAnchor).should("not.exist"); - cy.get(textinputFullCorrectAnchor).should("not.exist"); - cy.get(textinputFullIncorrectAnchor).should("not.exist"); - cy.get(textinputFullPartialAnchor).should("have.text", "50 %"); - - cy.log("incorrect answer"); - cy.get(textinputDefSugarAnchor).clear().type(`Hello{enter}`); - cy.get(textinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(textinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(textinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(textinputInsSugarAnchor).clear().type(`Hello{enter}`); - cy.get(textinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(textinputInsSugarCorrectAnchor).should("not.exist"); - cy.get(textinputInsSugarIncorrectAnchor).should("be.visible"); - - cy.get(textinputAwardAnchor).clear().type(`Hello{enter}`); - cy.get(textinputAwardSubmitAnchor).should("not.exist"); - cy.get(textinputAwardCorrectAnchor).should("not.exist"); - cy.get(textinputAwardIncorrectAnchor).should("be.visible"); - cy.get(textinputAwardPartialAnchor).should("not.exist"); - - cy.get(textinputFullAnchor).clear().type(`Hello{enter}`); - cy.get(textinputFullSubmitAnchor).should("not.exist"); - cy.get(textinputFullCorrectAnchor).should("not.exist"); - cy.get(textinputFullIncorrectAnchor).should("be.visible"); - cy.get(textinputFullPartialAnchor).should("not.exist"); - - cy.log("wrong case 3"); - cy.get(textinputDefSugarAnchor).clear().type(`hello There!{enter}`); - cy.get(textinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(textinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(textinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(textinputInsSugarAnchor).clear().type(`hello There!{enter}`); - cy.get(textinputInsSugarSubmitAnchor).should("not.exist"); - cy.get(textinputInsSugarCorrectAnchor).should("be.visible"); - cy.get(textinputInsSugarIncorrectAnchor).should("not.exist"); - - cy.get(textinputAwardAnchor).clear().type(`hello There!{enter}`); - cy.get(textinputAwardSubmitAnchor).should("not.exist"); - cy.get(textinputAwardCorrectAnchor).should("not.exist"); - cy.get(textinputAwardIncorrectAnchor).should("not.exist"); - cy.get(textinputAwardPartialAnchor).should("have.text", "50 %"); - - cy.get(textinputFullAnchor).clear().type(`hello There!{enter}`); - cy.get(textinputFullSubmitAnchor).should("not.exist"); - cy.get(textinputFullCorrectAnchor).should("not.exist"); - cy.get(textinputFullIncorrectAnchor).should("not.exist"); - cy.get(textinputFullPartialAnchor).should("have.text", "50 %"); }); }); - it("match blanks", () => { + it("submit label, choiceinput", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a -

Default, sugar: _6^14C

-

Match blanks, sugar: _6^14C

-

Default, shortcut award: - _6^14C -

-

Match blanks, shortcut award: - _6^14C -

-

Default, full syntax: - - - $deffullmi = _6^14C - -

-

Match blanks, full syntax: - - - $blankfullmi = _6^14C - -

+

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

+

+ + yes + no + +

`, }, "*", @@ -32657,206 +2852,139 @@ describe("Answer Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputDefSugarName = - stateVariables["/defSugar"].stateValues.inputChildren[0] - .componentName; - let mathinputDefSugarAnchor = - cesc2("#" + mathinputDefSugarName) + " textarea"; - let mathinputDefSugarSubmitAnchor = cesc2( - "#" + mathinputDefSugarName + "_submit", - ); - let mathinputDefSugarCorrectAnchor = cesc2( - "#" + mathinputDefSugarName + "_correct", - ); - let mathinputDefSugarIncorrectAnchor = cesc2( - "#" + mathinputDefSugarName + "_incorrect", - ); - let mathinputBlankSugarName = - stateVariables["/blankSugar"].stateValues.inputChildren[0] - .componentName; - let mathinputBlankSugarAnchor = - cesc2("#" + mathinputBlankSugarName) + " textarea"; - let mathinputBlankSugarSubmitAnchor = cesc2( - "#" + mathinputBlankSugarName + "_submit", - ); - let mathinputBlankSugarCorrectAnchor = cesc2( - "#" + mathinputBlankSugarName + "_correct", - ); - let mathinputBlankSugarIncorrectAnchor = cesc2( - "#" + mathinputBlankSugarName + "_incorrect", - ); - let mathinputDefShortName = - stateVariables["/defShort"].stateValues.inputChildren[0] - .componentName; - let mathinputDefShortAnchor = - cesc2("#" + mathinputDefShortName) + " textarea"; - let mathinputDefShortSubmitAnchor = cesc2( - "#" + mathinputDefShortName + "_submit", - ); - let mathinputDefShortCorrectAnchor = cesc2( - "#" + mathinputDefShortName + "_correct", - ); - let mathinputDefShortIncorrectAnchor = cesc2( - "#" + mathinputDefShortName + "_incorrect", - ); - let mathinputBlankShortName = - stateVariables["/blankShort"].stateValues.inputChildren[0] - .componentName; - let mathinputBlankShortAnchor = - cesc2("#" + mathinputBlankShortName) + " textarea"; - let mathinputBlankShortSubmitAnchor = cesc2( - "#" + mathinputBlankShortName + "_submit", - ); - let mathinputBlankShortCorrectAnchor = cesc2( - "#" + mathinputBlankShortName + "_correct", - ); - let mathinputBlankShortIncorrectAnchor = cesc2( - "#" + mathinputBlankShortName + "_incorrect", - ); - let mathinputDefFullName = "/deffullmi"; - let mathinputDefFullAnchor = - cesc2("#" + mathinputDefFullName) + " textarea"; - let mathinputDefFullSubmitAnchor = cesc2( - "#" + mathinputDefFullName + "_submit", - ); - let mathinputDefFullCorrectAnchor = cesc2( - "#" + mathinputDefFullName + "_correct", - ); - let mathinputDefFullIncorrectAnchor = cesc2( - "#" + mathinputDefFullName + "_incorrect", - ); - let mathinputBlankFullName = "/blankfullmi"; - let mathinputBlankFullAnchor = - cesc2("#" + mathinputBlankFullName) + " textarea"; - let mathinputBlankFullSubmitAnchor = cesc2( - "#" + mathinputBlankFullName + "_submit", - ); - let mathinputBlankFullCorrectAnchor = cesc2( - "#" + mathinputBlankFullName + "_correct", - ); - let mathinputBlankFullIncorrectAnchor = cesc2( - "#" + mathinputBlankFullName + "_incorrect", - ); + cy.get(cesc("#\\/_choiceinput1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Check Work"); + }); + cy.get(cesc("#\\/_choiceinput2_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Hit it!"); + }); + cy.get(cesc("#\\/_choiceinput3_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Check Work"); + }); + cy.get(cesc("#\\/_choiceinput4_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Hit it!"); + }); + + cy.get(cesc("#\\/_choiceinput1")) + .contains(`yes`) + .click({ force: true }); + cy.get(cesc("#\\/_choiceinput2")) + .contains(`yes`) + .click({ force: true }); + cy.get(cesc("#\\/_choiceinput3")) + .contains(`yes`) + .click({ force: true }); + cy.get(cesc("#\\/_choiceinput4")) + .contains(`yes`) + .click({ force: true }); + + cy.get(cesc("#\\/_choiceinput1_submit")).click(); + cy.get(cesc("#\\/_choiceinput2_submit")).click(); + cy.get(cesc("#\\/_choiceinput3_submit")).click(); + cy.get(cesc("#\\/_choiceinput4_submit")).click(); + + cy.get(cesc("#\\/_choiceinput1_correct")).should( + "contain.text", + "Correct", + ); + cy.get(cesc("#\\/_choiceinput2_correct")).should( + "contain.text", + "Correct", + ); + cy.get(cesc("#\\/_choiceinput3_correct")).should( + "contain.text", + "Correct", + ); + cy.get(cesc("#\\/_choiceinput4_correct")).should( + "contain.text", + "Correct", + ); + + cy.get("#testRunner_toggleControls").click(); + cy.get("#testRunner_showCorrectness").click(); + cy.wait(100); + cy.get("#testRunner_toggleControls").click(); + + cy.get(cesc("#\\/_choiceinput1_submit")).should( + "contain.text", + "Submit Response", + ); + cy.get(cesc("#\\/_choiceinput2_submit")).should( + "contain.text", + "Submit Response", + ); + cy.get(cesc("#\\/_choiceinput3_submit")).should( + "contain.text", + "Guess", + ); + cy.get(cesc("#\\/_choiceinput4_submit")).should( + "contain.text", + "Guess", + ); - cy.get(mathinputDefSugarSubmitAnchor).should("be.visible"); - cy.get(mathinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputDefSugarIncorrectAnchor).should("not.exist"); - cy.get(mathinputBlankSugarSubmitAnchor).should("be.visible"); - cy.get(mathinputBlankSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputBlankSugarIncorrectAnchor).should("not.exist"); - cy.get(mathinputDefShortSubmitAnchor).should("be.visible"); - cy.get(mathinputDefShortCorrectAnchor).should("not.exist"); - cy.get(mathinputDefShortIncorrectAnchor).should("not.exist"); - cy.get(mathinputBlankShortSubmitAnchor).should("be.visible"); - cy.get(mathinputBlankShortCorrectAnchor).should("not.exist"); - cy.get(mathinputBlankShortIncorrectAnchor).should("not.exist"); - cy.get(mathinputDefFullSubmitAnchor).should("be.visible"); - cy.get(mathinputDefFullCorrectAnchor).should("not.exist"); - cy.get(mathinputDefFullIncorrectAnchor).should("not.exist"); - cy.get(mathinputBlankFullSubmitAnchor).should("be.visible"); - cy.get(mathinputBlankFullCorrectAnchor).should("not.exist"); - cy.get(mathinputBlankFullIncorrectAnchor).should("not.exist"); - - cy.log("wrong answer"); - cy.get(mathinputDefSugarAnchor).type(`C_6{rightArrow}^14{enter}`, { - force: true, + cy.get(cesc("#\\/_choiceinput1_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Submit Response"); }); - cy.get(mathinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(mathinputBlankSugarAnchor).type( - `C_6{rightArrow}^14{enter}`, - { - force: true, - }, - ); - cy.get(mathinputBlankSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputBlankSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputBlankSugarIncorrectAnchor).should("be.visible"); - - cy.get(mathinputDefShortAnchor).type(`C_6{rightArrow}^14{enter}`, { - force: true, + cy.get(cesc("#\\/_choiceinput2_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Submit Response"); }); - cy.get(mathinputDefShortSubmitAnchor).should("not.exist"); - cy.get(mathinputDefShortCorrectAnchor).should("not.exist"); - cy.get(mathinputDefShortIncorrectAnchor).should("be.visible"); - - cy.get(mathinputBlankShortAnchor).type( - `C_6{rightArrow}^14{enter}`, - { - force: true, - }, - ); - cy.get(mathinputBlankShortSubmitAnchor).should("not.exist"); - cy.get(mathinputBlankShortCorrectAnchor).should("not.exist"); - cy.get(mathinputBlankShortIncorrectAnchor).should("be.visible"); - - cy.get(mathinputDefFullAnchor).type(`C_6{rightArrow}^14{enter}`, { - force: true, + cy.get(cesc("#\\/_choiceinput3_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Guess"); }); - cy.get(mathinputDefFullSubmitAnchor).should("not.exist"); - cy.get(mathinputDefFullCorrectAnchor).should("not.exist"); - cy.get(mathinputDefFullIncorrectAnchor).should("be.visible"); - - cy.get(mathinputBlankFullAnchor).type(`C_6{rightArrow}^14{enter}`, { - force: true, + cy.get(cesc("#\\/_choiceinput4_submit")) + .invoke("text") + .then((text) => { + expect(text.trim()).equal("Guess"); }); - cy.get(mathinputBlankFullSubmitAnchor).should("not.exist"); - cy.get(mathinputBlankFullCorrectAnchor).should("not.exist"); - cy.get(mathinputBlankFullIncorrectAnchor).should("be.visible"); - - cy.log("correct answer"); - cy.get(mathinputDefSugarAnchor).type( - `{ctrl+home}{rightarrow}{backspace}{ctrl+end}C{enter}`, - { force: true }, - ); - cy.get(mathinputDefSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputDefSugarCorrectAnchor).should("not.exist"); - cy.get(mathinputDefSugarIncorrectAnchor).should("be.visible"); - - cy.get(mathinputBlankSugarAnchor).type( - `{ctrl+home}{rightarrow}{backspace}{ctrl+end}C{enter}`, - { force: true }, - ); - cy.get(mathinputBlankSugarSubmitAnchor).should("not.exist"); - cy.get(mathinputBlankSugarCorrectAnchor).should("be.visible"); - cy.get(mathinputBlankSugarIncorrectAnchor).should("not.exist"); - - cy.get(mathinputDefShortAnchor).type( - `{ctrl+home}{rightarrow}{backspace}{ctrl+end}C{enter}`, - { force: true }, - ); - cy.get(mathinputDefShortSubmitAnchor).should("not.exist"); - cy.get(mathinputDefShortCorrectAnchor).should("not.exist"); - cy.get(mathinputDefShortIncorrectAnchor).should("be.visible"); - cy.get(mathinputBlankShortAnchor).type( - `{ctrl+home}{rightarrow}{backspace}{ctrl+end}C{enter}`, - { force: true }, - ); - cy.get(mathinputBlankShortSubmitAnchor).should("not.exist"); - cy.get(mathinputBlankShortCorrectAnchor).should("be.visible"); - cy.get(mathinputBlankShortIncorrectAnchor).should("not.exist"); + cy.get(cesc("#\\/_choiceinput1")) + .contains(`yes`) + .click({ force: true }); + cy.get(cesc("#\\/_choiceinput2")) + .contains(`yes`) + .click({ force: true }); + cy.get(cesc("#\\/_choiceinput3")) + .contains(`yes`) + .click({ force: true }); + cy.get(cesc("#\\/_choiceinput4")) + .contains(`yes`) + .click({ force: true }); - cy.get(mathinputDefFullAnchor).type( - `{ctrl+home}{rightarrow}{backspace}{ctrl+end}C{enter}`, - { force: true }, - ); - cy.get(mathinputDefFullSubmitAnchor).should("not.exist"); - cy.get(mathinputDefFullCorrectAnchor).should("not.exist"); - cy.get(mathinputDefFullIncorrectAnchor).should("be.visible"); + cy.get(cesc("#\\/_choiceinput1_submit")).click(); + cy.get(cesc("#\\/_choiceinput2_submit")).click(); + cy.get(cesc("#\\/_choiceinput3_submit")).click(); + cy.get(cesc("#\\/_choiceinput4_submit")).click(); - cy.get(mathinputBlankFullAnchor).type( - `{ctrl+home}{rightarrow}{backspace}{ctrl+end}C{enter}`, - { force: true }, - ); - cy.get(mathinputBlankFullSubmitAnchor).should("not.exist"); - cy.get(mathinputBlankFullCorrectAnchor).should("be.visible"); - cy.get(mathinputBlankFullIncorrectAnchor).should("not.exist"); - }); + cy.get(cesc("#\\/_choiceinput1_saved")).should( + "contain.text", + "Response Saved", + ); + cy.get(cesc("#\\/_choiceinput2_saved")).should( + "contain.text", + "Response Saved", + ); + cy.get(cesc("#\\/_choiceinput3_saved")).should( + "contain.text", + "Response Saved", + ); + cy.get(cesc("#\\/_choiceinput4_saved")).should( + "contain.text", + "Response Saved", + ); }); it("auto submit", () => { @@ -33214,368 +3342,29 @@ describe("Answer Tag Tests", function () { win.callAction1({ actionName: "movePoint", componentName: "/P", - args: { x: 9, y: 8 }, - }); - }); - - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow").should( - "contain.text", - "9", - ); - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow") - .eq(1) - .should("have.text", "8"); - - cy.get(cesc("#\\/pCreditFirstQuad")).should( - "have.text", - "Credit for this answer: 1", - ); - cy.get(cesc("#\\/pCreditDoc")).should( - "have.text", - "Document credit achieved: 1", - ); - }); - - it("submitted responses from copy source", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

x - - -

-

hello - - -

-

true - - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/xsr") + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(cesc("#\\/xcr") + " .mjx-mrow").should("contain.text", "\uff3f"); - - cy.get(cesc("#\\/x") + " textarea") - .type("x", { force: true }) - .blur(); - cy.get(cesc("#\\/xcr") + " .mjx-mrow").should("contain.text", "x"); - cy.get(cesc("#\\/xsr") + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(cesc("#\\/x") + " textarea").type("{enter}", { force: true }); - cy.get(cesc("#\\/xsr") + " .mjx-mrow").should("contain.text", "x"); - cy.get(cesc("#\\/xcr") + " .mjx-mrow").should("contain.text", "x"); - - cy.get(cesc("#\\/hellosr")).should("have.text", ""); - cy.get(cesc("#\\/hellocr")).should("have.text", ""); - - cy.get(cesc("#\\/hello") + " input") - .type("hello") - .blur(); - cy.get(cesc("#\\/hellocr")).should("have.text", "hello"); - cy.get(cesc("#\\/hellosr")).should("have.text", ""); - cy.get(cesc("#\\/hello") + " input").type("{enter}"); - cy.get(cesc("#\\/hellosr")).should("have.text", "hello"); - cy.get(cesc("#\\/hellocr")).should("have.text", "hello"); - - cy.get(cesc("#\\/bsr")).should("have.text", "false"); - cy.get(cesc("#\\/bcr")).should("have.text", "false"); - cy.get(cesc("#\\/b") + " .doenetml-checkmark").click(); - cy.get(cesc("#\\/bcr")).should("have.text", "true"); - cy.get(cesc("#\\/bsr")).should("have.text", "false"); - cy.get(cesc("#\\/b_submit")).click(); - cy.get(cesc("#\\/bsr")).should("have.text", "true"); - cy.get(cesc("#\\/bcr")).should("have.text", "true"); - }); - - it("parse scientific notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

4E3

-

4E3

-

4E3

-

4E3=$minp4

- -

4E3

-

4E3

-

4E3

-

4E3=$mip4

- - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/np1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/minp1") + " textarea").type("4E3{enter}", { - force: true, - }); - cy.get(cesc("#\\/minp1_correct")).should("be.visible"); - cy.get(cesc("#\\/np1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4E3"); - - cy.get(cesc("#\\/minp2") + " textarea").type("4E3{enter}", { - force: true, - }); - cy.get(cesc("#\\/minp2_correct")).should("be.visible"); - cy.get(cesc("#\\/np2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4E3"); - - cy.get(cesc("#\\/minp3") + " textarea").type("4E3{enter}", { - force: true, - }); - cy.get(cesc("#\\/minp3_correct")).should("be.visible"); - cy.get(cesc("#\\/np3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4E3"); - - cy.get(cesc("#\\/minp4") + " textarea").type("4E3{enter}", { - force: true, - }); - cy.get(cesc("#\\/minp4_correct")).should("be.visible"); - cy.get(cesc("#\\/np4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4E3"); - - cy.get(cesc("#\\/mip1") + " textarea").type("4E3{enter}", { - force: true, - }); - cy.get(cesc("#\\/mip1_correct")).should("be.visible"); - cy.get(cesc("#\\/p1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/mip2") + " textarea").type("4E3{enter}", { - force: true, - }); - cy.get(cesc("#\\/mip2_correct")).should("be.visible"); - cy.get(cesc("#\\/p2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/mip3") + " textarea").type("4E3{enter}", { - force: true, - }); - cy.get(cesc("#\\/mip3_correct")).should("be.visible"); - cy.get(cesc("#\\/p3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/mip4") + " textarea").type("4E3{enter}", { - force: true, - }); - cy.get(cesc("#\\/mip4_correct")).should("be.visible"); - cy.get(cesc("#\\/p4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/minp1") + " textarea").type( - "{end}{backspace}{backspace}{backspace}4000{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minp1_incorrect")).should("be.visible"); - cy.get(cesc("#\\/np1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/minp2") + " textarea").type( - "{end}{backspace}{backspace}{backspace}4000{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minp2_incorrect")).should("be.visible"); - cy.get(cesc("#\\/np2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/minp3") + " textarea").type( - "{end}{backspace}{backspace}{backspace}4000{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minp3_incorrect")).should("be.visible"); - cy.get(cesc("#\\/np3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/minp4") + " textarea").type( - "{end}{backspace}{backspace}{backspace}4000{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minp4_incorrect")).should("be.visible"); - cy.get(cesc("#\\/np4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/mip1") + " textarea").type( - "{end}{backspace}{backspace}{backspace}4000{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mip1_correct")).should("be.visible"); - cy.get(cesc("#\\/p1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/mip2") + " textarea").type( - "{end}{backspace}{backspace}{backspace}4000{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mip2_correct")).should("be.visible"); - cy.get(cesc("#\\/p2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/mip3") + " textarea").type( - "{end}{backspace}{backspace}{backspace}4000{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mip3_correct")).should("be.visible"); - cy.get(cesc("#\\/p3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - - cy.get(cesc("#\\/mip4") + " textarea").type( - "{end}{backspace}{backspace}{backspace}4000{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mip4_correct")).should("be.visible"); - cy.get(cesc("#\\/p4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "4000"); - }); - - it("submitted response from matrixInput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - a bc d - - -

current response: $ans.currentResponses

-

submitted response: $ans

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/pCurrent") + " .mjx-mrow") - .eq(0) - .should("have.text", "[οΌΏοΌΏοΌΏοΌΏ]"); - cy.get(cesc("#\\/pSubmitted") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/mi_component_0_0") + " textarea").type("x{enter}", { - force: true, - }); - - cy.get(cesc("#\\/pCurrent") + " .mjx-mrow") - .eq(0) - .should("have.text", "[xοΌΏοΌΏοΌΏ]"); - cy.get(cesc("#\\/pSubmitted") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/mi_component_0_1") + " textarea").type("y{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi_component_1_0") + " textarea").type("z{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi_component_1_1") + " textarea").type("0{enter}", { - force: true, - }); - - cy.get(cesc("#\\/pCurrent") + " .mjx-mrow") - .eq(0) - .should("have.text", "[xyz0]"); - cy.get(cesc("#\\/pSubmitted") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/mi_submit")).click(); - cy.get(cesc("#\\/mi_incorrect")).should("be.visible"); - - cy.get(cesc("#\\/pSubmitted") + " .mjx-mrow").should( - "contain.text", - "[xyz0]", - ); - cy.get(cesc("#\\/pCurrent") + " .mjx-mrow") - .eq(0) - .should("have.text", "[xyz0]"); - cy.get(cesc("#\\/pSubmitted") + " .mjx-mrow") - .eq(0) - .should("have.text", "[xyz0]"); - - cy.get(cesc("#\\/mi_component_0_0") + " textarea").type( - "{end}{backspace}a{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi_component_0_1") + " textarea").type( - "{end}{backspace}b{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi_component_1_0") + " textarea").type( - "{end}{backspace}c{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi_component_1_1") + " textarea").type( - "{end}{backspace}d{enter}", - { force: true }, - ); + args: { x: 9, y: 8 }, + }); + }); - cy.get(cesc("#\\/pCurrent") + " .mjx-mrow").should( + cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow").should( "contain.text", - "[abcd]", + "9", ); - cy.get(cesc("#\\/pCurrent") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]"); - cy.get(cesc("#\\/pSubmitted") + " .mjx-mrow") + cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow") .eq(0) - .should("have.text", "[xyz0]"); - - cy.get(cesc("#\\/mi_submit")).click(); - cy.get(cesc("#\\/mi_correct")).should("be.visible"); + .should("have.text", "9"); + cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow") + .eq(1) + .should("have.text", "8"); - cy.get(cesc("#\\/pSubmitted") + " .mjx-mrow").should( - "contain.text", - "[abcd]", + cy.get(cesc("#\\/pCreditFirstQuad")).should( + "have.text", + "Credit for this answer: 1", + ); + cy.get(cesc("#\\/pCreditDoc")).should( + "have.text", + "Document credit achieved: 1", ); - cy.get(cesc("#\\/pCurrent") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]"); - cy.get(cesc("#\\/pSubmitted") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]"); }); it("reload math answer without blurring or hitting enter", () => { @@ -33661,598 +3450,4 @@ describe("Answer Tag Tests", function () { cy.get(cesc("#\\/ti_submit")).click(); cy.get(cesc("#\\/ti_correct")).should("be.visible"); }); - - it("a function defined by formula uses formula for a response", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Type the function f(x) = x^2

-

f(x) =

- - - - $userFormula = $correctFunction - - - -

Submitted responses: $_answer1.submittedResponses{assignNames="sr1 sr2"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1")).should("contain.text", "Type the function"); - - cy.get(cesc("#\\/userFormula") + " textarea").type("x^2{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.get(cesc("#\\/_answer1_correct")).should("be.visible"); - - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x2"); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x2"); - - cy.get(cesc("#\\/userFormula") + " textarea").type("{home}3{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_answer1_submit")).click(); - - cy.get(cesc("#\\/_answer1_incorrect")).should("be.visible"); - - cy.get(cesc("#\\/sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "3x2"); - cy.get(cesc("#\\/sr2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x2"); - }); - - it("hand-graded answers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Maths: - - - - x - x - x - x -

-

Submitted responses: - - - - - - - -

-

Credit achieved: - - - - - - - -

-

Texts: - - - hello - hello -

-

Submitted responses: - - - - -

-

Credit achieved: - - - - -

-

Multiple inputs - - - -

-

Submitted responses: - - - - - - -

-

Credit achieved: - - - -

-

Inputs outside answer - $oi1i1$oi1i2 - $oi2i1$oi2i2 - $oi3i1$oi3i2 -

-

Submitted responses: - - - - - - -

-

Credit achieved: - - - -

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/m1") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/m2") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/m3") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/m4") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/m5") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/m6") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/m7") + " textarea").type("x{enter}", { force: true }); - - cy.get(cesc("#\\/t1") + " input").type("hello{enter}"); - cy.get(cesc("#\\/t2") + " input").type("hello{enter}"); - cy.get(cesc("#\\/t3") + " input").type("hello{enter}"); - cy.get(cesc("#\\/t4") + " input").type("hello{enter}"); - - cy.get(cesc("#\\/mi1") + " textarea") - .eq(0) - .type("x{enter}", { force: true }); - cy.get(cesc("#\\/mi1") + " textarea") - .eq(1) - .type("y{enter}", { force: true }); - cy.get(cesc("#\\/mi1_submit")).click(); - cy.get(cesc("#\\/mi2") + " input") - .eq(0) - .type("hello{enter}"); - cy.get(cesc("#\\/mi2") + " input") - .eq(1) - .type("bye{enter}"); - cy.get(cesc("#\\/mi2_submit")).click(); - cy.get(cesc("#\\/mi3") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/mi3") + " input").type("bye{enter}"); - cy.get(cesc("#\\/mi3_submit")).click(); - - cy.get(cesc("#\\/oi1i1") + " textarea").type("x{enter}", { - force: true, - }); - cy.get(cesc("#\\/oi1i2") + " textarea").type("y{enter}", { - force: true, - }); - cy.get(cesc("#\\/oi1_submit")).click(); - cy.get(cesc("#\\/oi2i1") + " input").type("hello{enter}"); - cy.get(cesc("#\\/oi2i2") + " input").type("bye{enter}"); - cy.get(cesc("#\\/oi2_submit")).click(); - cy.get(cesc("#\\/oi3i1") + " textarea").type("x{enter}", { - force: true, - }); - cy.get(cesc("#\\/oi3i2") + " input").type("bye{enter}"); - cy.get(cesc("#\\/oi3_submit")).click(); - - cy.get(cesc("#\\/oi3sr2")).should("have.text", "bye"); - - cy.get(cesc("#\\/m1sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/m2sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/m3sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/m4sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/m5sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/m6sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/m7sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc("#\\/t1sr")).should("have.text", "hello"); - cy.get(cesc("#\\/t2sr")).should("have.text", "hello"); - cy.get(cesc("#\\/t3sr")).should("have.text", "hello"); - cy.get(cesc("#\\/t4sr")).should("have.text", "hello"); - - cy.get(cesc("#\\/mi1sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/mi1sr2") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc("#\\/mi2sr1")).should("have.text", "hello"); - cy.get(cesc("#\\/mi2sr2")).should("have.text", "bye"); - cy.get(cesc("#\\/mi3sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/mi3sr2")).should("have.text", "bye"); - - cy.get(cesc("#\\/oi1sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/oi1sr2") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc("#\\/oi2sr1")).should("have.text", "hello"); - cy.get(cesc("#\\/oi2sr2")).should("have.text", "bye"); - cy.get(cesc("#\\/oi3sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/oi3sr2")).should("have.text", "bye"); - - cy.get(cesc("#\\/m1ca")).should("have.text", "0"); - cy.get(cesc("#\\/m2ca")).should("have.text", "0"); - cy.get(cesc("#\\/m3ca")).should("have.text", "0"); - cy.get(cesc("#\\/m4ca")).should("have.text", "0"); - cy.get(cesc("#\\/m5ca")).should("have.text", "0"); - cy.get(cesc("#\\/m6ca")).should("have.text", "0"); - cy.get(cesc("#\\/m7ca")).should("have.text", "0"); - - cy.get(cesc("#\\/t1ca")).should("have.text", "0"); - cy.get(cesc("#\\/t2ca")).should("have.text", "0"); - cy.get(cesc("#\\/t3ca")).should("have.text", "0"); - cy.get(cesc("#\\/t4ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi1ca")).should("have.text", "0"); - cy.get(cesc("#\\/mi2ca")).should("have.text", "0"); - cy.get(cesc("#\\/mi3ca")).should("have.text", "0"); - - cy.get(cesc("#\\/oi1ca")).should("have.text", "0"); - cy.get(cesc("#\\/oi2ca")).should("have.text", "0"); - cy.get(cesc("#\\/oi3ca")).should("have.text", "0"); - - cy.log("revise answers and submit"); - - cy.get(cesc("#\\/m1") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/m2") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/m3") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/m4") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/m5") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/m6") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/m7") + " textarea").type("{end}y{enter}", { - force: true, - }); - - cy.get(cesc("#\\/t1") + " input").type(" there{enter}"); - cy.get(cesc("#\\/t2") + " input").type(" there{enter}"); - cy.get(cesc("#\\/t3") + " input").type(" there{enter}"); - cy.get(cesc("#\\/t4") + " input").type(" there{enter}"); - - cy.get(cesc("#\\/mi1") + " textarea") - .eq(0) - .type("{end}z{enter}", { force: true }); - cy.get(cesc("#\\/mi1_submit")).click(); - cy.get(cesc("#\\/mi1") + " textarea") - .eq(1) - .type("{end}z{enter}", { force: true }); - cy.get(cesc("#\\/mi1_submit")).click(); - cy.get(cesc("#\\/mi2") + " input") - .eq(0) - .type(" there{enter}"); - cy.get(cesc("#\\/mi2_submit")).click(); - cy.get(cesc("#\\/mi2") + " input") - .eq(1) - .type(" now{enter}"); - cy.get(cesc("#\\/mi2_submit")).click(); - cy.get(cesc("#\\/mi3") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi3_submit")).click(); - cy.get(cesc("#\\/mi3") + " input").type(" now{enter}"); - cy.get(cesc("#\\/mi3_submit")).click(); - - cy.get(cesc("#\\/oi1i1") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/oi1_submit")).click(); - cy.get(cesc("#\\/oi1i2") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/oi1_submit")).click(); - cy.get(cesc("#\\/oi2i1") + " input").type(" there{enter}"); - cy.get(cesc("#\\/oi2_submit")).click(); - cy.get(cesc("#\\/oi2i2") + " input").type(" now{enter}"); - cy.get(cesc("#\\/oi2_submit")).click(); - cy.get(cesc("#\\/oi3i1") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/oi3_submit")).click(); - cy.get(cesc("#\\/oi3i2") + " input").type(" now{enter}"); - cy.get(cesc("#\\/oi3_submit")).click(); - - cy.get(cesc("#\\/oi3sr2")).should("have.text", "bye now"); - - cy.get(cesc("#\\/m1sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc("#\\/m2sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc("#\\/m3sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc("#\\/m4sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc("#\\/m5sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc("#\\/m6sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc("#\\/m7sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - - cy.get(cesc("#\\/t1sr")).should("have.text", "hello there"); - cy.get(cesc("#\\/t2sr")).should("have.text", "hello there"); - cy.get(cesc("#\\/t3sr")).should("have.text", "hello there"); - cy.get(cesc("#\\/t4sr")).should("have.text", "hello there"); - - cy.get(cesc("#\\/mi1sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "xz"); - cy.get(cesc("#\\/mi1sr2") + " .mjx-mrow") - .eq(0) - .should("have.text", "yz"); - cy.get(cesc("#\\/mi2sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/mi2sr2")).should("have.text", "bye now"); - cy.get(cesc("#\\/mi3sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc("#\\/mi3sr2")).should("have.text", "bye now"); - - cy.get(cesc("#\\/oi1sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "xz"); - cy.get(cesc("#\\/oi1sr2") + " .mjx-mrow") - .eq(0) - .should("have.text", "yz"); - cy.get(cesc("#\\/oi2sr1")).should("have.text", "hello there"); - cy.get(cesc("#\\/oi2sr2")).should("have.text", "bye now"); - cy.get(cesc("#\\/oi3sr1") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc("#\\/oi3sr2")).should("have.text", "bye now"); - - cy.get(cesc("#\\/m1ca")).should("have.text", "0"); - cy.get(cesc("#\\/m2ca")).should("have.text", "0"); - cy.get(cesc("#\\/m3ca")).should("have.text", "0"); - cy.get(cesc("#\\/m4ca")).should("have.text", "0"); - cy.get(cesc("#\\/m5ca")).should("have.text", "0"); - cy.get(cesc("#\\/m6ca")).should("have.text", "0"); - cy.get(cesc("#\\/m7ca")).should("have.text", "0"); - - cy.get(cesc("#\\/t1ca")).should("have.text", "0"); - cy.get(cesc("#\\/t2ca")).should("have.text", "0"); - cy.get(cesc("#\\/t3ca")).should("have.text", "0"); - cy.get(cesc("#\\/t4ca")).should("have.text", "0"); - - cy.get(cesc("#\\/mi1ca")).should("have.text", "0"); - cy.get(cesc("#\\/mi2ca")).should("have.text", "0"); - cy.get(cesc("#\\/mi3ca")).should("have.text", "0"); - - cy.get(cesc("#\\/oi1ca")).should("have.text", "0"); - cy.get(cesc("#\\/oi2ca")).should("have.text", "0"); - cy.get(cesc("#\\/oi3ca")).should("have.text", "0"); - }); - - it("display digits for credit achieved", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

- x - y - - Credit: -

- -

- x - y - - Credit: -

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/def") + " textarea").type("y{enter}", { force: true }); - cy.get(cesc2("#/long") + " textarea").type("y{enter}", { force: true }); - - cy.get(cesc2("#/def_credit")).should("have.text", "0.333"); - cy.get(cesc2("#/long_credit")).should("have.text", "0.33333333"); - }); - - it("display digits for responses", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

1.23456789 - Current response: - Submitted response: -

- -

1.23456789 - Current response: - Submitted response: -

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/def_cr") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/short_cr") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/def_sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/short_sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc2("#/def") + " textarea") - .type("1.23456789", { force: true }) - .blur(); - cy.get(cesc2("#/short") + " textarea") - .type("1.23456789", { force: true }) - .blur(); - - cy.get(cesc2("#/short_cr")).should("contain.text", "1.23"); - cy.get(cesc2("#/def_cr") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.23456789"); - cy.get(cesc2("#/short_cr") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.23"); - cy.get(cesc2("#/def_sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/short_sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc2("#/def") + " textarea") - .type("{enter}", { force: true }) - .blur(); - cy.get(cesc2("#/short") + " textarea") - .type("{enter}", { force: true }) - .blur(); - - cy.get(cesc2("#/short_sr")).should("contain.text", "1.23"); - - cy.get(cesc2("#/def_cr") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.23456789"); - cy.get(cesc2("#/short_cr") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.23"); - cy.get(cesc2("#/def_sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.23456789"); - cy.get(cesc2("#/short_sr") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.23"); - }); - - it("display digits for responses, turn math to number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

1.23456789 - Current response: - Submitted response: -

- -

1.23456789 - Current response: - Submitted response: -

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/def") + " textarea") - .type("1.23456789", { force: true }) - .blur(); - cy.get(cesc2("#/short") + " textarea") - .type("1.23456789", { force: true }) - .blur(); - - cy.get(cesc2("#/short_cr")).should("contain.text", "1.23"); - cy.get(cesc2("#/def_cr")).should("have.text", "1.23456789"); - cy.get(cesc2("#/short_cr")).should("have.text", "1.23"); - cy.get(cesc2("#/def_sr")).should("have.text", "NaN"); - cy.get(cesc2("#/short_sr")).should("have.text", "NaN"); - - cy.get(cesc2("#/def") + " textarea") - .type("{enter}", { force: true }) - .blur(); - cy.get(cesc2("#/short") + " textarea") - .type("{enter}", { force: true }) - .blur(); - - cy.get(cesc2("#/short_sr")).should("contain.text", "1.23"); - - cy.get(cesc2("#/def_cr")).should("have.text", "1.23456789"); - cy.get(cesc2("#/short_cr")).should("have.text", "1.23"); - cy.get(cesc2("#/def_sr")).should("have.text", "1.23456789"); - cy.get(cesc2("#/short_sr")).should("have.text", "1.23"); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/conditionalcontent.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/conditionalcontent.cy.js deleted file mode 100644 index d9b7d9361..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/conditionalcontent.cy.js +++ /dev/null @@ -1,3575 +0,0 @@ -import { cesc, cesc2 } from "@doenet/utils"; - -describe("Conditional Content Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - // tests without cases or else - - it("inline content containing sign of number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

You typed - - a positive number. - - - a negative number. - - - zero. - - - something else. - -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed something else.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type("10{enter}", { force: true }); - - cy.get("p" + cesc2("#/_p1")).should( - "contain.text", - "a positive number.", - ); - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed a positive number.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-5/9{enter}", - { force: true }, - ); - cy.get("p" + cesc2("#/_p1")).should( - "contain.text", - "a negative number.", - ); - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed a negative number.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}5-5{enter}", - { force: true }, - ); - cy.get("p" + cesc2("#/_p1")).should("contain.text", "zero."); - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed zero.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-x{enter}", - { force: true }, - ); - cy.get("p" + cesc2("#/_p1")).should("contain.text", "something else."); - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed something else.", - ); - }); - }); - - it("inline content containing sign of number, use XML entities", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

You typed - - a positive number. - - - a negative number. - - - zero. - - - something else. - -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed something else.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type("10{enter}", { force: true }); - cy.get("p" + cesc2("#/_p1")).should( - "contain.text", - "a positive number.", - ); - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed a positive number.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-5/9{enter}", - { force: true }, - ); - cy.get("p" + cesc2("#/_p1")).should( - "contain.text", - "a negative number.", - ); - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed a negative number.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}5-5{enter}", - { force: true }, - ); - cy.get("p" + cesc2("#/_p1")).should("contain.text", "zero."); - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed zero.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-x{enter}", - { force: true }, - ); - cy.get("p" + cesc2("#/_p1")).should("contain.text", "something else."); - cy.get("p" + cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed something else.", - ); - }); - }); - - it("block content containing sign of number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -
- -

You typed a positive number.

-
-
-
- -

You typed a negative number.

-
-
-
- -

You typed zero.

-
-
-
- -

You typed something else.

-
-
- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/_section1") + " p").should("not.exist"); - cy.get(cesc2("#/_section2") + " p").should("not.exist"); - cy.get(cesc2("#/_section3") + " p").should("not.exist"); - cy.get(cesc2("#/_section4") + " p") - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed something else.", - ); - }); - - cy.get(cesc2("#/n") + " textarea").type("10{enter}", { force: true }); - cy.get(cesc2("#/_section1") + " p").should( - "contain.text", - "a positive number.", - ); - cy.get(cesc2("#/_section1") + " p") - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed a positive number.", - ); - }); - cy.get(cesc2("#/_section2") + " p").should("not.exist"); - cy.get(cesc2("#/_section3") + " p").should("not.exist"); - cy.get(cesc2("#/_section4") + " p").should("not.exist"); - - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-5/9{enter}", - { force: true }, - ); - cy.get(cesc2("#/_section2") + " p").should( - "contain.text", - "a negative number.", - ); - cy.get(cesc2("#/_section1") + " p").should("not.exist"); - cy.get(cesc2("#/_section2") + " p") - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed a negative number.", - ); - }); - cy.get(cesc2("#/_section3") + " p").should("not.exist"); - cy.get(cesc2("#/_section4") + " p").should("not.exist"); - - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}5-5{enter}", - { force: true }, - ); - cy.get(cesc2("#/_section3") + " p").should("contain.text", "zero."); - cy.get(cesc2("#/_section1") + " p").should("not.exist"); - cy.get(cesc2("#/_section2") + " p").should("not.exist"); - cy.get(cesc2("#/_section3") + " p") - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed zero.", - ); - }); - cy.get(cesc2("#/_section4") + " p").should("not.exist"); - - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-x{enter}", - { force: true }, - ); - cy.get(cesc2("#/_section4") + " p").should( - "contain.text", - "something else.", - ); - cy.get(cesc2("#/_section1") + " p").should("not.exist"); - cy.get(cesc2("#/_section2") + " p").should("not.exist"); - cy.get(cesc2("#/_section3") + " p").should("not.exist"); - cy.get(cesc2("#/_section4") + " p") - .invoke("text") - .then((text) => { - expect(text.replace(/\s+/g, " ").trim()).equal( - "You typed something else.", - ); - }); - }); - - it("conditional text used as correct answer", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Enter a slope:

- -

If this is the slope at an equilibrium of a discrete dynamical system, the equilibrium is - - stableunstable - - - = - - - stable - - - unstable - - - - -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/_choiceinput1")).select(`stable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput1")).select(`unstable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - - cy.get(cesc2("#/m") + " textarea").type("3{enter}", { force: true }); - cy.get(cesc2("#/_choiceinput1")).select(`stable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput1")).select(`unstable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); - - cy.get(cesc2("#/m") + " textarea").type("{end}{backspace}-0.8{enter}", { - force: true, - }); - cy.get(cesc2("#/_choiceinput1")).select(`stable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc2("#/_choiceinput1")).select(`unstable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - - cy.get(cesc2("#/m") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}1/3{enter}", - { force: true }, - ); - cy.get(cesc2("#/_choiceinput1")).select(`stable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); - cy.get(cesc2("#/_choiceinput1")).select(`unstable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - - cy.get(cesc2("#/m") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-7/5{enter}", - { force: true }, - ); - cy.get(cesc2("#/_choiceinput1")).select(`stable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput1")).select(`unstable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_correct")).should("be.visible"); - - cy.get(cesc2("#/m") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc2("#/_choiceinput1")).select(`stable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - cy.get(cesc2("#/_choiceinput1")).select(`unstable`); - cy.get(cesc2("#/_choiceinput1_submit")).click(); - cy.get(cesc2("#/_choiceinput1_incorrect")).should("be.visible"); - }); - - it("conditional math used as correct answer", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Require positivenegative.

- -

Condition on x: - - - - - = - - - x > 0 - - - x < 0 - - - - -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/x_submit")).click(); - cy.get(cesc2("#/x_incorrect")).should("be.visible"); - - cy.get(cesc2("#/x") + " textarea").type("x > 0{enter}", { - force: true, - }); - cy.get(cesc2("#/x_incorrect")).should("be.visible"); - - cy.get(cesc2("#/x") + " textarea").type( - "{end}{backspace}{backspace}{backspace}< 0", - { force: true }, - ); - cy.get(cesc2("#/x_submit")).should("be.visible"); - cy.get(cesc2("#/x") + " textarea").type("{enter}", { force: true }); - cy.get(cesc2("#/x_incorrect")).should("be.visible"); - - cy.get(cesc2("#/c")).select(`negative`); - cy.get(cesc2("#/x_submit")).click(); - cy.get(cesc2("#/x_correct")).should("be.visible"); - - cy.get(cesc2("#/x") + " textarea").type( - "{end}{backspace}{backspace}{backspace}> 0", - { force: true }, - ); - cy.get(cesc2("#/x_submit")).should("be.visible"); - cy.get(cesc2("#/x") + " textarea").type("{enter}", { force: true }); - cy.get(cesc2("#/x_incorrect")).should("be.visible"); - - cy.get(cesc2("#/c")).select(`positive`); - cy.get(cesc2("#/x_submit")).click(); - cy.get(cesc2("#/x_correct")).should("be.visible"); - - cy.get(cesc2("#/x") + " textarea").type( - "{end}{backspace}{backspace}{backspace}< 0", - { force: true }, - ); - cy.get(cesc2("#/x_submit")).should("be.visible"); - cy.get(cesc2("#/x") + " textarea").type("{enter}", { force: true }); - cy.get(cesc2("#/x_incorrect")).should("be.visible"); - }); - - it("include blank string between tags", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - foxjumps - - - - - -

The $animal $verb.

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p")).should("have.text", ""); - - cy.get(cesc2("#/b")).click(); - - cy.get(cesc2("#/p")).should("have.text", "The fox jumps."); - }); - - it("assignNames gives blanks for strings but strings still displayed", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

- dog mouse cat -

- -

$a

- -

$b

- -

$c

- -

- -

$d

- -

$e

- -

$f

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/p1")).should("have.text", ""); - cy.get(cesc2("#/pa")).should("have.text", ""); - cy.get(cesc2("#/pb")).should("have.text", ""); - cy.get(cesc2("#/pc")).should("have.text", ""); - cy.get(cesc2("#/p2")).should("have.text", ""); - cy.get(cesc2("#/pd")).should("have.text", ""); - cy.get(cesc2("#/pe")).should("have.text", ""); - cy.get(cesc2("#/pf")).should("have.text", ""); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/p1")).should("contain.text", "dog mouse cat"); - cy.get(cesc2("#/pa")).should("have.text", "dog"); - cy.get(cesc2("#/pb")).should("have.text", ""); - cy.get(cesc2("#/pc")).should("have.text", "cat"); - cy.get(cesc2("#/p2")).should("contain.text", "dog mouse cat"); - cy.get(cesc2("#/pd")).should("have.text", "dog"); - cy.get(cesc2("#/pe")).should("have.text", ""); - cy.get(cesc2("#/pf")).should("have.text", "cat"); - - cy.log("enter 0"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc2("#/p1")).should("have.text", ""); - cy.get(cesc2("#/pa")).should("have.text", ""); - cy.get(cesc2("#/pb")).should("have.text", ""); - cy.get(cesc2("#/pc")).should("have.text", ""); - cy.get(cesc2("#/p2")).should("have.text", ""); - cy.get(cesc2("#/pd")).should("have.text", ""); - cy.get(cesc2("#/pe")).should("have.text", ""); - cy.get(cesc2("#/pf")).should("have.text", ""); - }); - - it("correctly withhold replacements when shadowing", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Hide greeting: - -

- -

Greeting is hidden: $hide. Greeting: Hello!

- -

Show copy: - -

- - $p - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/p")).should( - "have.text", - "Greeting is hidden: false. Greeting: Hello!", - ); - cy.get(cesc2("#/p2")).should("not.exist"); - - cy.get(cesc2("#/hide")).click(); - - cy.get(cesc2("#/p")).should( - "have.text", - "Greeting is hidden: true. Greeting: ", - ); - cy.get(cesc2("#/p2")).should("not.exist"); - - cy.get(cesc2("#/show_copy")).click(); - cy.get(cesc2("#/p2")).should( - "have.text", - "Greeting is hidden: true. Greeting: ", - ); - - cy.get(cesc2("#/hide")).click(); - - cy.get(cesc2("#/p")).should( - "have.text", - "Greeting is hidden: false. Greeting: Hello!", - ); - cy.get(cesc2("#/p2")).should( - "have.text", - "Greeting is hidden: false. Greeting: Hello!", - ); - }); - - // tests with cases or else - - it("case/else with single text, assign sub on copy", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

a: - dog - cat - mouse -

- -

a1: $a{assignNames="a1"}

- -

b:

- -

b1: $b{name="b1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/pa")).should("have.text", "a: mouse"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: mouse"); - cy.get(cesc2("#/pb")).should("have.text", "b: mouse"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: mouse"); - - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/b")).should("have.text", "mouse"); - cy.get(cesc2("#/b1")).should("have.text", "mouse"); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/pa")).should("have.text", "a: cat"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: cat"); - cy.get(cesc2("#/pb")).should("have.text", "b: cat"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: cat"); - - cy.get(cesc2("#/a1")).should("have.text", "cat"); - cy.get(cesc2("#/b")).should("have.text", "cat"); - cy.get(cesc2("#/b1")).should("have.text", "cat"); - - cy.log("enter 10"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}10{enter}", - { force: true }, - ); - - cy.get(cesc2("#/pa")).should("have.text", "a: mouse"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: mouse"); - cy.get(cesc2("#/pb")).should("have.text", "b: mouse"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: mouse"); - - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/b")).should("have.text", "mouse"); - cy.get(cesc2("#/b1")).should("have.text", "mouse"); - - cy.log("enter -1"); - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2("#/pa")).should("have.text", "a: dog"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: dog"); - cy.get(cesc2("#/pb")).should("have.text", "b: dog"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: dog"); - - cy.get(cesc2("#/a1")).should("have.text", "dog"); - cy.get(cesc2("#/b")).should("have.text", "dog"); - cy.get(cesc2("#/b1")).should("have.text", "dog"); - - cy.log("enter x"); - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc2("#/pa")).should("have.text", "a: mouse"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: mouse"); - cy.get(cesc2("#/pb")).should("have.text", "b: mouse"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: mouse"); - - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/b")).should("have.text", "mouse"); - cy.get(cesc2("#/b1")).should("have.text", "mouse"); - }); - - it("case/else with single text, initially assign sub", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

a: - dog - cat - mouse -

- -

a1: $a{name="a1"}

- -

b: $_conditionalcontent1{assignNames="b"}

- -

b1: $b{assignNames="b1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/pa")).should("have.text", "a: mouse"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: mouse"); - cy.get(cesc2("#/pb")).should("have.text", "b: mouse"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: mouse"); - - cy.get(cesc2("#/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/b1")).should("have.text", "mouse"); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/pa")).should("have.text", "a: cat"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: cat"); - cy.get(cesc2("#/pb")).should("have.text", "b: cat"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: cat"); - - cy.get(cesc2("#/a")).should("have.text", "cat"); - cy.get(cesc2("#/a1")).should("have.text", "cat"); - cy.get(cesc2("#/b1")).should("have.text", "cat"); - - cy.log("enter 10"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}10{enter}", { - force: true, - }); - - cy.get(cesc2("#/pa")).should("have.text", "a: mouse"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: mouse"); - cy.get(cesc2("#/pb")).should("have.text", "b: mouse"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: mouse"); - - cy.get(cesc2("#/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/b1")).should("have.text", "mouse"); - - cy.log("enter -11"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2("#/pa")).should("have.text", "a: dog"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: dog"); - cy.get(cesc2("#/pb")).should("have.text", "b: dog"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: dog"); - - cy.get(cesc2("#/a")).should("have.text", "dog"); - cy.get(cesc2("#/a1")).should("have.text", "dog"); - cy.get(cesc2("#/b1")).should("have.text", "dog"); - - cy.log("enter x"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc2("#/pa")).should("have.text", "a: mouse"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: mouse"); - cy.get(cesc2("#/pb")).should("have.text", "b: mouse"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: mouse"); - - cy.get(cesc2("#/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/b1")).should("have.text", "mouse"); - }); - - it("case/else with text, math, and optional", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

original: - dog x - optional text! - - cat y - - mouse z - -

- -

a1: $a{name="a1"}

-

b1: $b{name="b1"}

-

c1: $c{name="c1"}

-

d1: $d{name="d1"}

- -

copy:

- -

e1: $e{name="e1"}

-

f1: $f{name="f1"}

-

g1: $g{name="g1"}

-

h1: $h{name="h1"}

-

i1: $i{name="i1"}

- -

copied copy:

- -

j1: $j{name="j1"}

-

k1: $k{name="k1"}

-

l1: $l{name="l1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/e")).should("have.text", "mouse"); - cy.get(cesc2("#/e1")).should("have.text", "mouse"); - cy.get(cesc2("#/j")).should("have.text", "mouse"); - cy.get(cesc2("#/j1")).should("have.text", "mouse"); - - cy.get(cesc2("#/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc2("#/c")).should("not.exist"); - cy.get(cesc2("#/c1")).should("not.exist"); - cy.get(cesc2("#/g")).should("not.exist"); - cy.get(cesc2("#/g1")).should("not.exist"); - cy.get(cesc2("#/l")).should("not.exist"); - cy.get(cesc2("#/l1")).should("not.exist"); - - cy.get(cesc2("#/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/a")).should("have.text", "cat"); - cy.get(cesc2("#/a1")).should("have.text", "cat"); - cy.get(cesc2("#/e")).should("have.text", "cat"); - cy.get(cesc2("#/e1")).should("have.text", "cat"); - cy.get(cesc2("#/j")).should("have.text", "cat"); - cy.get(cesc2("#/j1")).should("have.text", "cat"); - - cy.get(cesc2("#/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc2("#/c")).should("not.exist"); - cy.get(cesc2("#/c1")).should("not.exist"); - cy.get(cesc2("#/g")).should("not.exist"); - cy.get(cesc2("#/g1")).should("not.exist"); - cy.get(cesc2("#/l")).should("not.exist"); - cy.get(cesc2("#/l1")).should("not.exist"); - - cy.get(cesc2("#/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - - cy.log("enter 10"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}10{enter}", { - force: true, - }); - - cy.get(cesc2("#/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/e")).should("have.text", "mouse"); - cy.get(cesc2("#/e1")).should("have.text", "mouse"); - cy.get(cesc2("#/j")).should("have.text", "mouse"); - cy.get(cesc2("#/j1")).should("have.text", "mouse"); - - cy.get(cesc2("#/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc2("#/c")).should("not.exist"); - cy.get(cesc2("#/c1")).should("not.exist"); - cy.get(cesc2("#/g")).should("not.exist"); - cy.get(cesc2("#/g1")).should("not.exist"); - cy.get(cesc2("#/l")).should("not.exist"); - cy.get(cesc2("#/l1")).should("not.exist"); - - cy.get(cesc2("#/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - - cy.log("enter -11"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2("#/a")).should("have.text", "dog"); - cy.get(cesc2("#/a1")).should("have.text", "dog"); - cy.get(cesc2("#/e")).should("have.text", "dog"); - cy.get(cesc2("#/e1")).should("have.text", "dog"); - cy.get(cesc2("#/j")).should("have.text", "dog"); - cy.get(cesc2("#/j1")).should("have.text", "dog"); - - cy.get(cesc2("#/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc2("#/c")).should("have.text", "optional text!"); - cy.get(cesc2("#/c1")).should("have.text", "optional text!"); - cy.get(cesc2("#/g")).should("have.text", "optional text!"); - cy.get(cesc2("#/g1")).should("have.text", "optional text!"); - cy.get(cesc2("#/l")).should("have.text", "optional text!"); - cy.get(cesc2("#/l1")).should("have.text", "optional text!"); - - cy.get(cesc2("#/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - - cy.log("enter x"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc2("#/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/e")).should("have.text", "mouse"); - cy.get(cesc2("#/e1")).should("have.text", "mouse"); - cy.get(cesc2("#/j")).should("have.text", "mouse"); - cy.get(cesc2("#/j1")).should("have.text", "mouse"); - - cy.get(cesc2("#/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc2("#/c")).should("not.exist"); - cy.get(cesc2("#/c1")).should("not.exist"); - cy.get(cesc2("#/g")).should("not.exist"); - cy.get(cesc2("#/g1")).should("not.exist"); - cy.get(cesc2("#/l")).should("not.exist"); - cy.get(cesc2("#/l1")).should("not.exist"); - - cy.get(cesc2("#/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - }); - - it("case/else with text, math, and optional, new namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

original: - dog x - optional text! - - cat y - - mouse z - -

- -

a1: $(s1/a{name="a1"})

-

b1: $(s1/b{name="b1"})

-

c1: $(s1/c{name="c1"})

-

d1: $(s1/d{name="d1"})

- -

copy:

- -

e1: $(s2/e{name="e1"})

-

f1: $(s2/f{name="f1"})

-

g1: $(s2/g{name="g1"})

-

h1: $(s2/h{name="h1"})

-

i1: $(s2/i{name="i1"})

- -

copied copy:

- -

j1: $(s3/j{name="j1"})

-

k1: $(s3/k{name="k1"})

-

l1: $(s3/l{name="l1"})

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/s1/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/s2/e")).should("have.text", "mouse"); - cy.get(cesc2("#/e1")).should("have.text", "mouse"); - cy.get(cesc2("#/s3/j")).should("have.text", "mouse"); - cy.get(cesc2("#/j1")).should("have.text", "mouse"); - - cy.get(cesc2("#/s1/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/s2/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/s3/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc2("#/s1/c")).should("not.exist"); - cy.get(cesc2("#/c1")).should("not.exist"); - cy.get(cesc2("#/s2/g")).should("not.exist"); - cy.get(cesc2("#/g1")).should("not.exist"); - cy.get(cesc2("#/s3/l")).should("not.exist"); - cy.get(cesc2("#/l1")).should("not.exist"); - - cy.get(cesc2("#/s1/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/s2/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/s2/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/s1/a")).should("have.text", "cat"); - cy.get(cesc2("#/a1")).should("have.text", "cat"); - cy.get(cesc2("#/s2/e")).should("have.text", "cat"); - cy.get(cesc2("#/e1")).should("have.text", "cat"); - cy.get(cesc2("#/s3/j")).should("have.text", "cat"); - cy.get(cesc2("#/j1")).should("have.text", "cat"); - - cy.get(cesc2("#/s1/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/s2/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/s3/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc2("#/s1/c")).should("not.exist"); - cy.get(cesc2("#/c1")).should("not.exist"); - cy.get(cesc2("#/s2/g")).should("not.exist"); - cy.get(cesc2("#/g1")).should("not.exist"); - cy.get(cesc2("#/s3/l")).should("not.exist"); - cy.get(cesc2("#/l1")).should("not.exist"); - - cy.get(cesc2("#/s1/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/s2/h")).should("not.exist"); - cy.get(cesc2("#h1")).should("not.exist"); - cy.get(cesc2("#/s2/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - - cy.log("enter 10"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}10{enter}", - { force: true }, - ); - - cy.get(cesc2("#/s1/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/s2/e")).should("have.text", "mouse"); - cy.get(cesc2("#/e1")).should("have.text", "mouse"); - cy.get(cesc2("#/s3/j")).should("have.text", "mouse"); - cy.get(cesc2("#/j1")).should("have.text", "mouse"); - - cy.get(cesc2("#/s1/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/s2/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/s3/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc2("#/s1/c")).should("not.exist"); - cy.get(cesc2("#/c1")).should("not.exist"); - cy.get(cesc2("#/s2/g")).should("not.exist"); - cy.get(cesc2("#/g1")).should("not.exist"); - cy.get(cesc2("#/s3/l")).should("not.exist"); - cy.get(cesc2("#/l1")).should("not.exist"); - - cy.get(cesc2("#/s1/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/s2/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/s2/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - - cy.log("enter -1"); - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2("#/s1/a")).should("have.text", "dog"); - cy.get(cesc2("#/a1")).should("have.text", "dog"); - cy.get(cesc2("#/s2/e")).should("have.text", "dog"); - cy.get(cesc2("#/e1")).should("have.text", "dog"); - cy.get(cesc2("#/s3/j")).should("have.text", "dog"); - cy.get(cesc2("#/j1")).should("have.text", "dog"); - - cy.get(cesc2("#/s1/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/s2/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/s3/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc2("#/s1/c")).should("have.text", "optional text!"); - cy.get(cesc2("#/c1")).should("have.text", "optional text!"); - cy.get(cesc2("#/s2/g")).should("have.text", "optional text!"); - cy.get(cesc2("#/g1")).should("have.text", "optional text!"); - cy.get(cesc2("#/s3/l")).should("have.text", "optional text!"); - cy.get(cesc2("#/l1")).should("have.text", "optional text!"); - - cy.get(cesc2("#/s1/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/s2/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/s2/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - - cy.log("enter x"); - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc2("#/s1/a")).should("have.text", "mouse"); - cy.get(cesc2("#/a1")).should("have.text", "mouse"); - cy.get(cesc2("#/s2/e")).should("have.text", "mouse"); - cy.get(cesc2("#/e1")).should("have.text", "mouse"); - cy.get(cesc2("#/s3/j")).should("have.text", "mouse"); - cy.get(cesc2("#/j1")).should("have.text", "mouse"); - - cy.get(cesc2("#/s1/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/b1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/s2/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/s3/k")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2("#/k1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc2("#/s1/c")).should("not.exist"); - cy.get(cesc2("#/c1")).should("not.exist"); - cy.get(cesc2("#/s2/g")).should("not.exist"); - cy.get(cesc2("#/g1")).should("not.exist"); - cy.get(cesc2("#/s3/l")).should("not.exist"); - cy.get(cesc2("#/l1")).should("not.exist"); - - cy.get(cesc2("#/s1/d")).should("not.exist"); - cy.get(cesc2("#/d1")).should("not.exist"); - cy.get(cesc2("#/s2/h")).should("not.exist"); - cy.get(cesc2("#/h1")).should("not.exist"); - cy.get(cesc2("#/s2/i")).should("not.exist"); - cy.get(cesc2("#/i1")).should("not.exist"); - }); - - it("references to internal and external components", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - dog - cat - mouse - - -

original: - - $x1 - $y1 - 3xa + $a1$b1 - - - $x2 - $y2 - 4yb + $a2$b2 - - - $x3 - $y3 - 5zc + $a3$b3 - -

- - tree - shrub - bush - -

Selected options repeated

- $a{name="aa"} - $b{name="bb"} - $c{name="cc"} - -

Whole thing repeated

- - -

Selected options repeated from copy

- $d{name="dd"} - $e{name="ee"} - $f{name="ff"} - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2(`#/a`)).should("have.text", "mouse"); - cy.get(cesc2(`#/b`)).should("have.text", "bush"); - cy.get(cesc2(`#/c`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/aa`)).should("have.text", "mouse"); - cy.get(cesc2(`#/bb`)).should("have.text", "bush"); - cy.get(cesc2(`#/cc`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/d`)).should("have.text", "mouse"); - cy.get(cesc2(`#/e`)).should("have.text", "bush"); - cy.get(cesc2(`#/f`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/dd`)).should("have.text", "mouse"); - cy.get(cesc2(`#/ee`)).should("have.text", "bush"); - cy.get(cesc2(`#/ff`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc2(`#/a`)).should("have.text", "cat"); - cy.get(cesc2(`#/b`)).should("have.text", "shrub"); - cy.get(cesc2(`#/c`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - cy.get(cesc2(`#/aa`)).should("have.text", "cat"); - cy.get(cesc2(`#/bb`)).should("have.text", "shrub"); - cy.get(cesc2(`#/cc`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - - cy.get(cesc2(`#/d`)).should("have.text", "cat"); - cy.get(cesc2(`#/e`)).should("have.text", "shrub"); - cy.get(cesc2(`#/f`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - cy.get(cesc2(`#/dd`)).should("have.text", "cat"); - cy.get(cesc2(`#/ee`)).should("have.text", "shrub"); - cy.get(cesc2(`#/ff`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - - cy.log("enter -1"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}-1{enter}", { - force: true, - }); - - cy.get(cesc2(`#/a`)).should("have.text", "dog"); - cy.get(cesc2(`#/b`)).should("have.text", "tree"); - cy.get(cesc2(`#/c`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - cy.get(cesc2(`#/aa`)).should("have.text", "dog"); - cy.get(cesc2(`#/bb`)).should("have.text", "tree"); - cy.get(cesc2(`#/cc`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(cesc2(`#/d`)).should("have.text", "dog"); - cy.get(cesc2(`#/e`)).should("have.text", "tree"); - cy.get(cesc2(`#/f`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - cy.get(cesc2(`#/dd`)).should("have.text", "dog"); - cy.get(cesc2(`#/ee`)).should("have.text", "tree"); - cy.get(cesc2(`#/ff`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.log("enter 10"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}10{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/a`)).should("have.text", "mouse"); - cy.get(cesc2(`#/b`)).should("have.text", "bush"); - cy.get(cesc2(`#/c`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/aa`)).should("have.text", "mouse"); - cy.get(cesc2(`#/bb`)).should("have.text", "bush"); - cy.get(cesc2(`#/cc`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/d`)).should("have.text", "mouse"); - cy.get(cesc2(`#/e`)).should("have.text", "bush"); - cy.get(cesc2(`#/f`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/dd`)).should("have.text", "mouse"); - cy.get(cesc2(`#/ee`)).should("have.text", "bush"); - cy.get(cesc2(`#/ff`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - }); - - it("references to internal and external components, new namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - dog - cat - mouse - - -

original: - - $(../x1{name="animal"}) - $(../y1{name="plant"}) - 3xa + $x$a - - - $(../x2{name="animal"}) - $(../y2{name="plant"}) - 4yb + $x$a - - - $(../x3{name="animal"}) - $(../y3{name="plant"}) - 5zc + $x$a - -

- - tree - shrub - bush - -

Selected options repeated

- $(a/animal{name="animal"}) - $(a/plant{name="plant"}) - $(a/p{name="p"}) - $(a/x{name="xx"}) - $(a/a{name="aa"}) - -

Whole thing repeated

- - -

Selected options repeated from copy

- $(b/animal{name="animalcopy"}) - $(b/plant{name="plantcopy"}) - $(b/p{name="pcopy"}) - $(b/x{name="xxcopy"}) - $(b/a{name="aacopy"}) - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2(`#/a/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/a/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.get(cesc2(`#/b/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/b/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "bush"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}1{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/a/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/a/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.get(cesc2(`#/b/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/b/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "cat"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "shrub"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.log("enter -1"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/a/animal`)).should("have.text", "dog"); - cy.get(cesc2(`#/a/plant`)).should("have.text", "tree"); - cy.get(cesc2(`#/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "dog"); - cy.get(cesc2(`#/plant`)).should("have.text", "tree"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.get(cesc2(`#/b/animal`)).should("have.text", "dog"); - cy.get(cesc2(`#/b/plant`)).should("have.text", "tree"); - cy.get(cesc2(`#/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "dog"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "tree"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.log("enter 10"); - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}10{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/a/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/a/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.get(cesc2(`#/b/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/b/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "bush"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - }); - - it("references to internal and external components, multiple layers of new namespaces", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - dog - cat - mouse - - -

original: - - $(../../x1{name="animal"}) - $(../../y1{name="plant"}) - 3xa + $x$a - - - $(../../x2{name="animal"}) - $(../../y2{name="plant"}) - 4yb + $x$a - - - $(../../x3{name="animal"}) - $(../../y3{name="plant"}) - 5zc + $x$a - -

- - tree - shrub - bush - -

Selected options repeated

- $(s/a/animal{name="animal"}) - $(s/a/plant{name="plant"}) - $(s/a/p{name="p"}) - $(s/a/x{name="xx"}) - $(s/a/a{name="aa"}) - -

Whole thing repeated

- - -

Selected options repeated from copy

- $(s2/b/animal{name="animalcopy"}) - $(s2/b/plant{name="plantcopy"}) - $(s2/b/p{name="pcopy"}) - $(s2/b/x{name="xxcopy"}) - $(s2/b/a{name="aacopy"}) - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2(`#/s/a/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/s/a/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/s/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.get(cesc2(`#/s2/b/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/s2/b/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/s2/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "bush"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}1{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/s/a/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/s/a/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/s/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.get(cesc2(`#/s2/b/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/s2/b/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/s2/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "cat"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "shrub"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.log("enter -1"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/s/a/animal`)).should("have.text", "dog"); - cy.get(cesc2(`#/s/a/plant`)).should("have.text", "tree"); - cy.get(cesc2(`#/s/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "dog"); - cy.get(cesc2(`#/plant`)).should("have.text", "tree"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.get(cesc2(`#/s2/b/animal`)).should("have.text", "dog"); - cy.get(cesc2(`#/s2/b/plant`)).should("have.text", "tree"); - cy.get(cesc2(`#/s2/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "dog"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "tree"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.log("enter 10"); - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}10{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/s/a/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/s/a/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/s/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.get(cesc2(`#/s2/b/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/s2/b/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/s2/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "bush"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - }); - - it("references to internal and external components, inconsistent new namespaces", () => { - // not sure why would want to do this, as give inconsistent behavior - // depending on which option is chosen - // but, we handle it gracefully - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - dog - cat - mouse - - -

original: - - $x1{name="theanimal"} - $y1{name="theplant"} - 3xa + $thex$thea - - - $(../x2{name="animal"}) - $(../y2{name="plant"}) - 4yb + $x$a - - - $(../x3{name="animal"}) - $(../y3{name="plant"}) - 5zc + $x$a - -

- - tree - shrub - bush - -

Selected options repeated

- $(a/animal{name="animal"}) - $(a/plant{name="plant"}) - $(a/p{name="p"}) - $(a/x{name="xx"}) - $(a/a{name="aa"}) - -

Whole thing repeated

-

- -

Selected options repeated from copy

- $(b/animal{name="animalcopy"}) - $(b/plant{name="plantcopy"}) - $(b/p{name="pcopy"}) - $(b/x{name="xxcopy"}) - $(b/a{name="aacopy"}) - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2(`#/a/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/a/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.get(cesc2(`#/b/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/b/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "bush"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}1{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/a/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/a/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.get(cesc2(`#/b/animal`)).should("have.text", "cat"); - cy.get(cesc2(`#/b/plant`)).should("have.text", "shrub"); - cy.get(cesc2(`#/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "cat"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "shrub"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5by"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.log("enter -1"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/a/animal`)).should("not.exist"); - cy.get(cesc2(`#/a/plant`)).should("not.exist"); - cy.get(cesc2(`#/a/p`)).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let p1Chidren = stateVariables["/_p1"].activeChildren; - let theAnimalAnchor = cesc2("#" + p1Chidren[2].componentName); - let thePlantAnchor = cesc2("#" + p1Chidren[4].componentName); - let thePAnchor = cesc2("#" + p1Chidren[6].componentName); - - let repeatChildren = stateVariables["/_p1"].activeChildren; - let theAnimalCopyAnchor = cesc2( - "#" + repeatChildren[2].componentName, - ); - let thePlantCopyAnchor = cesc2( - "#" + repeatChildren[4].componentName, - ); - let thePCopyAnchor = cesc2("#" + repeatChildren[6].componentName); - - cy.get(cesc2(`#/_p1`)) - .invoke("text") - .then((text) => { - let words = text.split(/\s+/).slice(1); - expect(words[0]).eq("dog"); - expect(words[1]).eq("tree"); - }); - cy.get(cesc2(`#/_p1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(theAnimalAnchor).should("have.text", "dog"); - cy.get(thePlantAnchor).should("have.text", "tree"); - cy.get(thePAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(cesc2(`#/animal`)).should("not.exist"); - cy.get(cesc2(`#/plant`)).should("not.exist"); - cy.get(cesc2(`#/p`)).should("not.exist"); - cy.get(cesc2(`#/xx`)).should("not.exist"); - cy.get(cesc2(`#/aa`)).should("not.exist"); - - cy.get(cesc2(`#/b/animal`)).should("not.exist"); - cy.get(cesc2(`#/b/plant`)).should("not.exist"); - cy.get(cesc2(`#/b/p`)).should("not.exist"); - - cy.get(cesc2(`#/repeat`)) - .invoke("text") - .then((text) => { - let words = text.split(/\s+/).slice(1); - expect(words[0]).eq("dog"); - expect(words[1]).eq("tree"); - }); - cy.get(cesc2(`#/repeat`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(theAnimalCopyAnchor).should("have.text", "dog"); - cy.get(thePlantCopyAnchor).should("have.text", "tree"); - cy.get(thePCopyAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4ax"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("not.exist"); - cy.get(cesc2(`#/plantcopy`)).should("not.exist"); - cy.get(cesc2(`#/pcopy`)).should("not.exist"); - cy.get(cesc2(`#/xxcopy`)).should("not.exist"); - cy.get(cesc2(`#/aacopy`)).should("not.exist"); - }); - - cy.log("enter 10"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}10{enter}", - { force: true }, - ); - - cy.get(cesc2(`#/a/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/a/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/a/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xx`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.get(cesc2(`#/b/animal`)).should("have.text", "mouse"); - cy.get(cesc2(`#/b/plant`)).should("have.text", "bush"); - cy.get(cesc2(`#/b/p`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - - cy.get(cesc2(`#/animalcopy`)).should("have.text", "mouse"); - cy.get(cesc2(`#/plantcopy`)).should("have.text", "bush"); - cy.get(cesc2(`#/pcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6cz"); - }); - cy.get(cesc2(`#/xxcopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc2(`#/aacopy`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - }); - - it("dynamic internal references", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

What is your favorite animal?

-

I like , too.

-
- -

What is your name?

-

Hello, !

-
- -

Anything else?

-

To repeat: .

-
-
- -

The response:

- - - -

The response one more time:

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2(`#/a/_p1`)).should("have.text", "What is your name? "); - cy.get(cesc2(`#/a/_p2`)).should("have.text", "Hello, !"); - cy.get(cesc2(`#/_p1`)).should("have.text", "The response: "); - cy.get(cesc2(`#/b/_p1`)).should("have.text", "What is your name? "); - cy.get(cesc2(`#/b/_p2`)).should("have.text", "Hello, !"); - cy.get(cesc2(`#/_p2`)).should( - "have.text", - "The response one more time: ", - ); - - cy.get(cesc2(`#/a/response_input`)).clear().type("Fred{enter}"); - cy.get(cesc2(`#/a/_p2`)).should("have.text", "Hello, Fred!"); - cy.get(cesc2(`#/_p1`)).should("have.text", "The response: Fred"); - cy.get(cesc2(`#/b/_p2`)).should("have.text", "Hello, Fred!"); - cy.get(cesc2(`#/_p2`)).should( - "have.text", - "The response one more time: Fred", - ); - - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}-1{enter}", { - force: true, - }); - cy.get(cesc2(`#/a/_p1`)).should( - "have.text", - "What is your favorite animal? ", - ); - cy.get(cesc2(`#/a/_p2`)).should("have.text", "I like , too."); - cy.get(cesc2(`#/_p1`)).should("have.text", "The response: "); - cy.get(cesc2(`#/b/_p1`)).should( - "have.text", - "What is your favorite animal? ", - ); - cy.get(cesc2(`#/b/_p2`)).should("have.text", "I like , too."); - cy.get(cesc2(`#/_p2`)).should( - "have.text", - "The response one more time: ", - ); - - cy.get(cesc2(`#/a/response_input`)).clear().type("dogs{enter}"); - cy.get(cesc2(`#/a/_p2`)).should("have.text", "I like dogs, too."); - cy.get(cesc2(`#/_p1`)).should("have.text", "The response: dogs"); - cy.get(cesc2(`#/b/_p2`)).should("have.text", "I like dogs, too."); - cy.get(cesc2(`#/_p2`)).should( - "have.text", - "The response one more time: dogs", - ); - - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc2(`#/a/_p1`)).should("have.text", "Anything else? "); - cy.get(cesc2(`#/a/_p2`)).should("have.text", "To repeat: ."); - cy.get(cesc2(`#/_p1`)).should("have.text", "The response: "); - cy.get(cesc2(`#/b/_p1`)).should("have.text", "Anything else? "); - cy.get(cesc2(`#/b/_p2`)).should("have.text", "To repeat: ."); - cy.get(cesc2(`#/_p2`)).should( - "have.text", - "The response one more time: ", - ); - - cy.get(cesc2(`#/a/response_input`)).clear().type("Goodbye{enter}"); - cy.get(cesc2(`#/a/_p2`)).should("have.text", "To repeat: Goodbye."); - cy.get(cesc2(`#/_p1`)).should("have.text", "The response: Goodbye"); - cy.get(cesc2(`#/b/_p2`)).should("have.text", "To repeat: Goodbye."); - cy.get(cesc2(`#/_p2`)).should( - "have.text", - "The response one more time: Goodbye", - ); - }); - - it("dynamic internal references, assign pieces", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

What is your favorite animal?

-

I like , too.

-
- -

What is your name?

-

Hello, !

-
- -

Anything else?

-

To repeat: .

-
-
- -

The response:

- - - -

The response one more time:

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2(`#/a`)).should("have.text", "What is your name? "); - cy.get(cesc2(`#/b`)).should("have.text", "Hello, !"); - cy.get(cesc2(`#/pResponse`)).should("have.text", "The response: "); - cy.get(cesc2(`#/c`)).should("have.text", "What is your name? "); - cy.get(cesc2(`#/d`)).should("have.text", "Hello, !"); - cy.get(cesc2(`#/pResponse2`)).should( - "have.text", - "The response one more time: ", - ); - - cy.get(cesc2(`#/a/response_input`)).clear().type("Fred{enter}"); - cy.get(cesc2(`#/b`)).should("have.text", "Hello, Fred!"); - cy.get(cesc2(`#/pResponse`)).should("have.text", "The response: Fred"); - cy.get(cesc2(`#/d`)).should("have.text", "Hello, Fred!"); - cy.get(cesc2(`#/pResponse2`)).should( - "have.text", - "The response one more time: Fred", - ); - - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}-1{enter}", { - force: true, - }); - cy.get(cesc2(`#/a`)).should( - "have.text", - "What is your favorite animal? ", - ); - cy.get(cesc2(`#/b`)).should("have.text", "I like , too."); - cy.get(cesc2(`#/pResponse`)).should("have.text", "The response: "); - cy.get(cesc2(`#/c`)).should( - "have.text", - "What is your favorite animal? ", - ); - cy.get(cesc2(`#/d`)).should("have.text", "I like , too."); - cy.get(cesc2(`#/pResponse2`)).should( - "have.text", - "The response one more time: ", - ); - - cy.get(cesc2(`#/a/response_input`)).clear().type("dogs{enter}"); - cy.get(cesc2(`#/b`)).should("have.text", "I like dogs, too."); - cy.get(cesc2(`#/pResponse`)).should("have.text", "The response: dogs"); - cy.get(cesc2(`#/d`)).should("have.text", "I like dogs, too."); - cy.get(cesc2(`#/pResponse2`)).should( - "have.text", - "The response one more time: dogs", - ); - - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc2(`#/a`)).should("have.text", "Anything else? "); - cy.get(cesc2(`#/b`)).should("have.text", "To repeat: ."); - cy.get(cesc2(`#/pResponse`)).should("have.text", "The response: "); - cy.get(cesc2(`#/c`)).should("have.text", "Anything else? "); - cy.get(cesc2(`#/d`)).should("have.text", "To repeat: ."); - cy.get(cesc2(`#/pResponse2`)).should( - "have.text", - "The response one more time: ", - ); - - cy.get(cesc2(`#/a/response_input`)).clear().type("Goodbye{enter}"); - cy.get(cesc2(`#/b`)).should("have.text", "To repeat: Goodbye."); - cy.get(cesc2(`#/pResponse`)).should( - "have.text", - "The response: Goodbye", - ); - cy.get(cesc2(`#/d`)).should("have.text", "To repeat: Goodbye."); - cy.get(cesc2(`#/pResponse2`)).should( - "have.text", - "The response one more time: Goodbye", - ); - }); - - it("copy case", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- positive - non-positive -

- -

- - negative - neither -

- - -

$_conditionalcontent1

- -

$_conditionalcontent2

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/_p1")).should("have.text", "non-positive"); - cy.get(cesc2("#/_p3")).should("have.text", "non-positive"); - cy.get(cesc2("#/_p2")).should("have.text", "neither"); - cy.get(cesc2("#/_p4")).should("have.text", "neither"); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc2("#/_p1")).should("have.text", "positive"); - cy.get(cesc2("#/_p3")).should("have.text", "positive"); - cy.get(cesc2("#/_p2")).should("have.text", "positive"); - cy.get(cesc2("#/_p4")).should("have.text", "positive"); - - cy.log("enter -1"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2("#/_p1")).should("have.text", "non-positive"); - cy.get(cesc2("#/_p3")).should("have.text", "non-positive"); - cy.get(cesc2("#/_p2")).should("have.text", "negative"); - cy.get(cesc2("#/_p4")).should("have.text", "negative"); - - cy.log("enter 0"); - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}0{enter}", - { force: true }, - ); - - cy.get(cesc2("#/_p1")).should("have.text", "non-positive"); - cy.get(cesc2("#/_p3")).should("have.text", "non-positive"); - cy.get(cesc2("#/_p2")).should("have.text", "neither"); - cy.get(cesc2("#/_p4")).should("have.text", "neither"); - }); - - it("copy else", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- hello - bye -

- -

- hello - oops - -

- -

$_conditionalcontent1

- -

$_conditionalcontent2

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/_p1")).should("have.text", "bye"); - cy.get(cesc2("#/_p3")).should("have.text", "bye"); - cy.get(cesc2("#/_p2")).should("have.text", "bye"); - cy.get(cesc2("#/_p4")).should("have.text", "bye"); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc2("#/_p1")).should("have.text", "hello"); - cy.get(cesc2("#/_p3")).should("have.text", "hello"); - cy.get(cesc2("#/_p2")).should("have.text", "oops"); - cy.get(cesc2("#/_p4")).should("have.text", "oops"); - - cy.log("enter -1"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - - cy.get(cesc2("#/_p1")).should("have.text", "bye"); - cy.get(cesc2("#/_p3")).should("have.text", "bye"); - cy.get(cesc2("#/_p2")).should("have.text", "hello"); - cy.get(cesc2("#/_p4")).should("have.text", "hello"); - - cy.log("enter 0"); - cy.get(cesc2("#/n") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}0{enter}", - { force: true }, - ); - - cy.get(cesc2("#/_p1")).should("have.text", "bye"); - cy.get(cesc2("#/_p3")).should("have.text", "bye"); - cy.get(cesc2("#/_p2")).should("have.text", "bye"); - cy.get(cesc2("#/_p4")).should("have.text", "bye"); - }); - - it("conditionalcontents hide dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - -

a: - dog - cat - mouse -

-

b: - dog - cat - mouse -

-

a1:

-

b1:

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc2("#/pa")).should("have.text", "a: mouse"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: mouse"); - cy.get(cesc2("#/pb")).should("have.text", "b: "); - cy.get(cesc2("#/pb1")).should("have.text", "b1: mouse"); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/pa")).should("have.text", "a: cat"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: cat"); - cy.get(cesc2("#/pb")).should("have.text", "b: "); - cy.get(cesc2("#/pb1")).should("have.text", "b1: cat"); - - cy.get(cesc2("#/h1")).click(); - cy.get(cesc2("#/h2")).click(); - - cy.get(cesc2("#/pa")).should("have.text", "a: "); - cy.get(cesc2("#/pa1")).should("have.text", "a1: cat"); - cy.get(cesc2("#/pb")).should("have.text", "b: cat"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: cat"); - - cy.log("enter -3"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}-3{enter}", { - force: true, - }); - - cy.get(cesc2("#/pa")).should("have.text", "a: "); - cy.get(cesc2("#/pa1")).should("have.text", "a1: dog"); - cy.get(cesc2("#/pb")).should("have.text", "b: dog"); - cy.get(cesc2("#/pb1")).should("have.text", "b1: dog"); - - cy.get(cesc2("#/h1")).click(); - cy.get(cesc2("#/h2")).click(); - - cy.get(cesc2("#/pa")).should("have.text", "a: dog"); - cy.get(cesc2("#/pa1")).should("have.text", "a1: dog"); - cy.get(cesc2("#/pb")).should("have.text", "b: "); - cy.get(cesc2("#/pb1")).should("have.text", "b1: dog"); - }); - - it("string and blank strings in case and else", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - foxjumps - elephanttrumpets - - - -

a: - The $animal1 $verb1. - The $animal2 $verb2. -

- -

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

- -

pieces:

- -

b1: $b{name="b1"}

-

c1: $c{name="c1"}

-

d1: $d{name="d1"}

-

e1: $e{name="e1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/pa")).should("have.text", "a: The elephant trumpets."); - cy.get(cesc2("#/pa1")).should( - "have.text", - "a1: The elephant trumpets.", - ); - cy.get(cesc2("#/ppieces")).should( - "have.text", - "pieces: The elephant trumpets.", - ); - cy.get(cesc2("#/pb1")).should("have.text", "b1: "); - cy.get(cesc2("#/pc1")).should("have.text", "c1: elephant"); - cy.get(cesc2("#/pd1")).should("have.text", "d1: trumpets"); - cy.get(cesc2("#/pe1")).should("have.text", "e1: "); - - cy.get(cesc2("#/a11")).should("not.exist"); - cy.get(cesc2("#/a12")).should("have.text", "elephant"); - cy.get(cesc2("#/a13")).should("have.text", "trumpets"); - cy.get(cesc2("#/a14")).should("not.exist"); - cy.get(cesc2("#/b1")).should("not.exist"); - cy.get(cesc2("#/c1")).should("have.text", "elephant"); - cy.get(cesc2("#/d1")).should("have.text", "trumpets"); - cy.get(cesc2("#/e1")).should("not.exist"); - - cy.log("enter 1"); - cy.get(cesc2("#/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/pa")).should("have.text", "a: The fox jumps."); - cy.get(cesc2("#/pa1")).should("have.text", "a1: The fox jumps."); - cy.get(cesc2("#/ppieces")).should( - "have.text", - "pieces: The fox jumps.", - ); - cy.get(cesc2("#/pb1")).should("have.text", "b1: "); - cy.get(cesc2("#/pc1")).should("have.text", "c1: fox"); - cy.get(cesc2("#/pd1")).should("have.text", "d1: jumps"); - cy.get(cesc2("#/pe1")).should("have.text", "e1: "); - - cy.get(cesc2("#/a11")).should("not.exist"); - cy.get(cesc2("#/a12")).should("have.text", "fox"); - cy.get(cesc2("#/a13")).should("have.text", "jumps"); - cy.get(cesc2("#/a14")).should("not.exist"); - cy.get(cesc2("#/b1")).should("not.exist"); - cy.get(cesc2("#/c1")).should("have.text", "fox"); - cy.get(cesc2("#/d1")).should("have.text", "jumps"); - cy.get(cesc2("#/e1")).should("not.exist"); - - cy.log("enter 0"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc2("#/pa")).should("have.text", "a: The elephant trumpets."); - cy.get(cesc2("#/pa1")).should( - "have.text", - "a1: The elephant trumpets.", - ); - cy.get(cesc2("#/ppieces")).should( - "have.text", - "pieces: The elephant trumpets.", - ); - cy.get(cesc2("#/pb1")).should("have.text", "b1: "); - cy.get(cesc2("#/pc1")).should("have.text", "c1: elephant"); - cy.get(cesc2("#/pd1")).should("have.text", "d1: trumpets"); - cy.get(cesc2("#/pe1")).should("have.text", "e1: "); - - cy.get(cesc2("#/a11")).should("not.exist"); - cy.get(cesc2("#/a12")).should("have.text", "elephant"); - cy.get(cesc2("#/a13")).should("have.text", "trumpets"); - cy.get(cesc2("#/a14")).should("not.exist"); - cy.get(cesc2("#/b1")).should("not.exist"); - cy.get(cesc2("#/c1")).should("have.text", "elephant"); - cy.get(cesc2("#/d1")).should("have.text", "trumpets"); - cy.get(cesc2("#/e1")).should("not.exist"); - }); - - it("copy with invalid source gets expanded", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - before - - nothing: - - after - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/n") + " textarea") - .type("1", { force: true }) - .blur(); - - cy.get(cesc2("#/_document1")).should( - "contain.text", - "a\n 1\n before\n nothing: \n after\n ", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - // don't currently have a way to check for isExpanded or replacements - // expect(stateVariables["/a/nothing"].isExpanded).eq(true) - // expect(stateVariables["/a/nothing"].replacements).eqls([]) - expect( - stateVariables["/_document1"].activeChildren.filter( - (x) => x.componentType === "copy", - ), - ).eqls([]); - }); - }); - - it("use original names if no assignNames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

We have a first winner!

-
- - - -

Just emphasizing that we have that first winner!

-
- -

We have a second winner!

-
- -

We have a third winner!

-
- -

We have no winner.

-
-
- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/winner1")).should("not.exist"); - cy.get(cesc2("#/_p1")).should("not.exist"); - cy.get(cesc2("#/winner1b")).should("not.exist"); - cy.get(cesc2("#/_p2")).should("not.exist"); - cy.get(cesc2("#/winner2")).should("not.exist"); - cy.get(cesc2("#/_p3")).should("not.exist"); - cy.get(cesc2("#/winner3")).should("not.exist"); - cy.get(cesc2("#/_p4")).should("not.exist"); - cy.get(cesc2("#/winner0")).should("have.text", "no winner"); - cy.get(cesc2("#/_p5")).should("have.text", "We have no winner."); - - cy.get(cesc2("#/n") + " textarea") - .type("1", { force: true }) - .blur(); - - cy.get(cesc2("#/winner1")).should("have.text", "first winner"); - cy.get(cesc2("#/_p1")).should("have.text", "We have a first winner!"); - cy.get(cesc2("#/winner1b")).should("have.text", "first winner"); - cy.get(cesc2("#/_p2")).should( - "have.text", - "Just emphasizing that we have that first winner!", - ); - cy.get(cesc2("#/winner2")).should("not.exist"); - cy.get(cesc2("#/_p3")).should("not.exist"); - cy.get(cesc2("#/winner3")).should("not.exist"); - cy.get(cesc2("#/_p4")).should("not.exist"); - cy.get(cesc2("#/winner0")).should("not.exist"); - cy.get(cesc2("#/_p5")).should("not.exist"); - - cy.get(cesc2("#/n") + " textarea") - .type("{end}{backspace}2", { force: true }) - .blur(); - - cy.get(cesc2("#/winner1")).should("have.text", "first winner"); - cy.get(cesc2("#/_p1")).should("have.text", "We have a first winner!"); - cy.get(cesc2("#/winner1b")).should("not.exist"); - cy.get(cesc2("#/_p2")).should("not.exist"); - cy.get(cesc2("#/winner2")).should("have.text", "second winner"); - cy.get(cesc2("#/_p3")).should("have.text", "We have a second winner!"); - cy.get(cesc2("#/winner3")).should("not.exist"); - cy.get(cesc2("#/_p4")).should("not.exist"); - cy.get(cesc2("#/winner0")).should("not.exist"); - cy.get(cesc2("#/_p5")).should("not.exist"); - - cy.get(cesc2("#/n") + " textarea") - .type("{end}{backspace}3", { force: true }) - .blur(); - - cy.get(cesc2("#/winner1")).should("have.text", "first winner"); - cy.get(cesc2("#/_p1")).should("have.text", "We have a first winner!"); - cy.get(cesc2("#/winner1b")).should("not.exist"); - cy.get(cesc2("#/_p2")).should("not.exist"); - cy.get(cesc2("#/winner2")).should("not.exist"); - cy.get(cesc2("#/_p3")).should("not.exist"); - cy.get(cesc2("#/winner3")).should("have.text", "third winner"); - cy.get(cesc2("#/_p4")).should("have.text", "We have a third winner!"); - cy.get(cesc2("#/winner0")).should("not.exist"); - cy.get(cesc2("#/_p5")).should("not.exist"); - - cy.get(cesc2("#/n") + " textarea") - .type("{end}{backspace}x", { force: true }) - .blur(); - - cy.get(cesc2("#/winner1")).should("not.exist"); - cy.get(cesc2("#/_p1")).should("not.exist"); - cy.get(cesc2("#/winner1b")).should("not.exist"); - cy.get(cesc2("#/_p2")).should("not.exist"); - cy.get(cesc2("#/winner2")).should("not.exist"); - cy.get(cesc2("#/_p3")).should("not.exist"); - cy.get(cesc2("#/winner3")).should("not.exist"); - cy.get(cesc2("#/_p4")).should("not.exist"); - cy.get(cesc2("#/winner0")).should("have.text", "no winner"); - cy.get(cesc2("#/_p5")).should("have.text", "We have no winner."); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/integer.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/integer.cy.js deleted file mode 100644 index 7dd2922b9..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/integer.cy.js +++ /dev/null @@ -1,194 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; - -describe("Integer Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("1.2+1.1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - $_integer1{name="int"} - 1.2+1.1 - `, - }, - "*", - ); - }); - - cy.log("Test value displayed in browser"); - cy.get(cesc2("#/int")).should("have.text", "2"); - cy.get(cesc2("#/_integer1")).should("have.text", "2"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/int"].stateValues.value).eq(2); - expect(stateVariables["/_integer1"].stateValues.value).eq(2); - }); - }); - - it(`non-numeric value`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - $_integer1{name="int"} - x+1 - `, - }, - "*", - ); - }); - - cy.log("Test value displayed in browser"); - cy.get(cesc2("#/int")).should("have.text", "NaN"); - cy.get(cesc2("#/_integer1")).should("have.text", "NaN"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - assert.isNaN(stateVariables["/int"].stateValues.value); - assert.isNaN(stateVariables["/_integer1"].stateValues.value); - }); - }); - - it(`entering non-integer values dynamically`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - $_mathinput1 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/n")).should("have.text", "NaN"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}-6.5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n")).should("have.text", "-6"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "βˆ’6.5", - ); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}x{enter}", { - force: true, - }); - cy.get(cesc("#\\/n")).should("have.text", "NaN"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "βˆ’6.5x", - ); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}9.5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n")).should("have.text", "10"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "9.5", - ); - }); - }); - - it(`entering non-integer through inverse`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 5 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/n")).should("have.text", "5"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}-6.5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n")).should("have.text", "-6"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "βˆ’6", - ); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}x{enter}", { - force: true, - }); - cy.get(cesc("#\\/n")).should("have.text", "NaN"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "NaN", - ); - }); - - // Note: change to 3 and then 31 to verify bug doesn't reappear - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("3"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}1{enter}", { - force: true, - }); - cy.get(cesc("#\\/n")).should("have.text", "31"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "31", - ); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}.5{enter}", { - force: true, - }); - cy.get(cesc("#\\/n")).should("have.text", "32"); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "32", - ); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/lorem.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/lorem.cy.js deleted file mode 100644 index 3253246d2..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/lorem.cy.js +++ /dev/null @@ -1,293 +0,0 @@ -import { cesc, cesc2 } from "@doenet/utils"; - -describe("Lorem Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("paragraphs, sentences, and words", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -
- Paragraphs - -

Number of paragraphs:

- - -
- -
- Sentences - -

Number of sentences:

- -

- -
- -
- Words - -

Number of words:

- -

-
- -

- $(words/numWords.value{assignNames="numWords"}) -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - let names = ["a", "b", "c", "d", "e", "f"]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let nParagraphs = 3, - nSentences = 3, - nWords = 3; - - expect(stateVariables["/paragraphs/lPars"].replacements.length).eq( - nParagraphs, - ); - expect(stateVariables["/sentences/lSens"].replacements.length).eq( - 2 * nSentences - 1, - ); - expect(stateVariables["/words/lWords"].replacements.length).eq( - 2 * nWords - 1, - ); - - for (let [ind, repl] of stateVariables[ - "/paragraphs/lPars" - ].replacements.entries()) { - cy.get(cesc2(`#/paragraphs/${names[ind]}`)).should( - "have.text", - stateVariables[repl.componentName].activeChildren[0], - ); - } - - for (let [ind, repl] of stateVariables[ - "/sentences/lSens" - ].replacements.entries()) { - if (ind % 2 === 1) { - continue; - } - cy.get(cesc2(`#/sentences/${names[ind / 2]}`)).should( - "have.text", - stateVariables[repl.componentName].activeChildren[0], - ); - } - - for (let [ind, repl] of stateVariables[ - "/words/lWords" - ].replacements.entries()) { - if (ind % 2 === 1) { - continue; - } - cy.get(cesc2(`#/words/${names[ind / 2]}`)).should( - "have.text", - stateVariables[repl.componentName].activeChildren[0], - ); - } - }); - - cy.get(cesc2("#/paragraphs/numPars") + " textarea").type( - "{end}{backspace}6{enter}", - { force: true }, - ); - cy.get(cesc2("#/sentences/numSens") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc2("#/words/numWords") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - - cy.get(cesc2("#/numWords")).should("contain.text", "5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let nParagraphs = 6, - nSentences = 2, - nWords = 5; - - expect(stateVariables["/paragraphs/lPars"].replacements.length).eq( - nParagraphs, - ); - expect(stateVariables["/sentences/lSens"].replacements.length).eq( - 2 * nSentences - 1, - ); - expect(stateVariables["/words/lWords"].replacements.length).eq( - 2 * nWords - 1, - ); - - for (let [ind, repl] of stateVariables[ - "/paragraphs/lPars" - ].replacements.entries()) { - cy.get(cesc2(`#/paragraphs/${names[ind]}`)).should( - "have.text", - stateVariables[repl.componentName].activeChildren[0], - ); - } - - for (let [ind, repl] of stateVariables[ - "/sentences/lSens" - ].replacements.entries()) { - if (ind % 2 === 1) { - continue; - } - cy.get(cesc2(`#/sentences/${names[ind / 2]}`)).should( - "have.text", - stateVariables[repl.componentName].activeChildren[0], - ); - } - - for (let [ind, repl] of stateVariables[ - "/words/lWords" - ].replacements.entries()) { - if (ind % 2 === 1) { - continue; - } - cy.get(cesc2(`#/words/${names[ind / 2]}`)).should( - "have.text", - stateVariables[repl.componentName].activeChildren[0], - ); - } - }); - }); - - it("changes only with variant", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - `, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc2("#/n")).should("have.text", "1"); - - let paragraph0, paragraph1; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/lPars"].replacements.length).eq(1); - paragraph0 = - stateVariables[ - stateVariables["/lPars"].replacements[0].componentName - ].activeChildren[0]; - cy.get(cesc2("#/a")).should("have.text", paragraph0); - }); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b - - - `, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "b"); // to wait for page to load - - cy.get(cesc2("#/n")).should("have.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/lPars"].replacements.length).eq(1); - expect( - stateVariables[ - stateVariables["/lPars"].replacements[0].componentName - ].activeChildren[0], - ).eq(paragraph0); - cy.get(cesc2("#/a")).should("have.text", paragraph0); - }); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c - - - `, - requestedVariantIndex: 2, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "c"); // to wait for page to load - - cy.get(cesc2("#/n")).should("have.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/lPars"].replacements.length).eq(1); - - paragraph1 = - stateVariables[ - stateVariables["/lPars"].replacements[0].componentName - ].activeChildren[0]; - expect(paragraph1).not.eq(paragraph0); - cy.get(cesc2("#/a")).should("have.text", paragraph1); - }); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - d - - - `, - requestedVariantIndex: 2, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "d"); // to wait for page to load - - cy.get(cesc2("#/n")).should("have.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/lPars"].replacements.length).eq(1); - expect( - stateVariables[ - stateVariables["/lPars"].replacements[0].componentName - ].activeChildren[0], - ).eq(paragraph1); - cy.get(cesc2("#/a")).should("have.text", paragraph1); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/math.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/math.cy.js index 3efec9e40..0f3e1d6f3 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/math.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/math.cy.js @@ -6,58 +6,31 @@ describe("Math Tag Tests", function () { cy.visit("/"); }); - it("1+1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 1+1 - 1+1 - `, - }, - "*", - ); - }); + // show hidden math doesn't appear in DOM? - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + it("changes are reloaded correctly.", () => { + let doenetML = ` +

a

+

w

+

x + y

+

z

+

a+$m4

+

+

+

+

+

+ `; - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+1"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - 1, - ]); - expect(stateVariables["/_math2"].stateValues.value).eq(2); - }); - }); + cy.get("#testRunner_toggleControls").click(); + cy.get("#testRunner_allowLocalState").click(); + cy.wait(100); + cy.get("#testRunner_toggleControls").click(); - it("string math string", () => { cy.window().then(async (win) => { win.postMessage( { - doenetML: ` - a - 3x+1+5 - 3x+1+5 - `, + doenetML, }, "*", ); @@ -65,251 +38,175 @@ describe("Math Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") + cy.get(cesc("#\\/m1") + " .mjx-mrow") .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3(x+1)+5"); - }); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x+1)"); - }); + .should("have.text", "w"); + cy.get(cesc("#\\/m2") + " .mjx-mrow") + .eq(0) + .should("have.text", "x+y"); + cy.get(cesc("#\\/m4") + " .mjx-mrow") + .eq(0) + .should("have.text", "z"); + cy.get(cesc("#\\/m5") + " .mjx-mrow") + .eq(0) + .should("have.text", "a+z"); - cy.log("Test internal values are set to the correct values"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - ["*", 3, ["+", "x", 1]], - 5, - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ + expect(stateVariables["/m1"].stateValues.value).eqls("w"); + expect(stateVariables["/m2"].stateValues.value).eqls([ "+", "x", - 1, + "y", ]); - expect(stateVariables["/_math3"].stateValues.value).eqls([ + expect(stateVariables["/m3"].stateValues.value).eqls("y"); + expect(stateVariables["/m4"].stateValues.value).eqls("z"); + expect(stateVariables["/m5"].stateValues.value).eqls([ "+", - 5, - ["*", 3, ["+", "x", 1]], + "a", + "z", ]); }); - }); - it("hidden string copy/math string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x+1 - 3$_math1{name="m1a"} + 5 - `, - }, - "*", - ); + cy.get(cesc("#\\/mi1") + " textarea").type("{end}{backspace}1{enter}", { + force: true, + }); + cy.get(cesc("#\\/mi2") + " textarea").type("{end}{backspace}2{enter}", { + force: true, + }); + cy.get(cesc("#\\/mi4") + " textarea").type("{end}{backspace}3{enter}", { + force: true, }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc("#\\/m4") + " .mjx-mrow").should("contain.text", "3"); - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") + cy.get(cesc("#\\/m1") + " .mjx-mrow") .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3(x+1)+5"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x+1)"); - }); + .should("have.text", "1"); + cy.get(cesc("#\\/m2") + " .mjx-mrow") + .eq(0) + .should("have.text", "x+2"); + cy.get(cesc("#\\/m4") + " .mjx-mrow") + .eq(0) + .should("have.text", "3"); + cy.get(cesc("#\\/m5") + " .mjx-mrow") + .eq(0) + .should("have.text", "a+3"); - cy.log("Test internal values are set to the correct values"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/m1a"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "+", - ["*", 3, ["+", "x", 1]], - 5, - ]); - expect(stateVariables["/_math1"].stateValues.hide).eq(true); - expect(stateVariables["/m1a"].stateValues.hide).eq(true); - expect(stateVariables["/_math2"].stateValues.hide).eq(false); + expect(stateVariables["/m1"].stateValues.value).eqls(1); + expect(stateVariables["/m2"].stateValues.value).eqls(["+", "x", 2]); + expect(stateVariables["/m3"].stateValues.value).eqls(2); + expect(stateVariables["/m4"].stateValues.value).eqls(3); + expect(stateVariables["/m5"].stateValues.value).eqls(["+", "a", 3]); }); - }); - it("math underscore when no value", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); + cy.wait(1500); // wait for debounce - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // wait to load - cy.get(".mjx-charbox") - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); + cy.reload(); cy.window().then(async (win) => { win.postMessage( { - doenetML: ` - b - - `, + doenetML, }, "*", ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "b"); // wait to load - cy.get(".mjx-charbox") - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); + cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "c"); // wait to load - cy.get(".mjx-charbox") - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - }); + // wait until core is loaded + cy.waitUntil(() => + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + return stateVariables["/m1"]; + }), + ); + + cy.get(cesc("#\\/m1") + " .mjx-mrow") + .eq(0) + .should("have.text", "1"); + cy.get(cesc("#\\/m2") + " .mjx-mrow") + .eq(0) + .should("have.text", "x+2"); + cy.get(cesc("#\\/m4") + " .mjx-mrow") + .eq(0) + .should("have.text", "3"); + cy.get(cesc("#\\/m5") + " .mjx-mrow") + .eq(0) + .should("have.text", "a+3"); - it("format latex", () => { cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - \\frac{x}{z} - `, - }, - "*", - ); + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables["/m1"].stateValues.value).eqls(1); + expect(stateVariables["/m2"].stateValues.value).eqls(["+", "x", 2]); + expect(stateVariables["/m3"].stateValues.value).eqls(2); + expect(stateVariables["/m4"].stateValues.value).eqls(3); + expect(stateVariables["/m5"].stateValues.value).eqls(["+", "a", 3]); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc("#\\/mi1") + " textarea").type( + "{end}{backspace}4+5{enter}", + { + force: true, + }, + ); + cy.get(cesc("#\\/mi3") + " textarea").type( + "{end}{backspace}6+7{enter}", + { + force: true, + }, + ); + cy.get(cesc("#\\/mi5") + " textarea").type( + "{end}{backspace}8+9{enter}", + { + force: true, + }, + ); + + cy.get(cesc("#\\/m5") + " .mjx-mrow").should("contain.text", "17"); - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-char") + cy.get(cesc("#\\/m1") + " .mjx-mrow") .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/_math1")) - .find(".mjx-char") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); + .should("have.text", "4+5"); + cy.get(cesc("#\\/m2") + " .mjx-mrow") + .eq(0) + .should("have.text", "x+6+7"); + cy.get(cesc("#\\/m4") + " .mjx-mrow") + .eq(0) + .should("have.text", "17"); + cy.get(cesc("#\\/m5") + " .mjx-mrow") + .eq(0) + .should("have.text", "a+17"); - cy.log("Test internal values are set to the correct values"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "/", + expect(stateVariables["/m1"].stateValues.value).eqls(["+", 4, 5]); + expect(stateVariables["/m2"].stateValues.value).eqls([ + "+", "x", - "z", + 6, + 7, + ]); + expect(stateVariables["/m3"].stateValues.value).eqls(["+", 6, 7]); + expect(stateVariables["/m4"].stateValues.value).eqls(17); + expect(stateVariables["/m5"].stateValues.value).eqls([ + "+", + "a", + 17, ]); - }); - }); - - it("copy latex property", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x/y - - `, - }, - "*", - ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.wait(1500); // wait for debounce - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-char") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/_math1")) - .find(".mjx-char") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacement = stateVariables["/_copy1"].replacements[0]; - cy.get(cesc2("#" + replacement.componentName)).should( - "have.text", - "\\frac{x}{y}", - ); - }); - }); + cy.reload(); - it("math with internal and external copies", () => { cy.window().then(async (win) => { win.postMessage( { - doenetML: ` - a - x + $x + $z - z - $a{name="a2"} - `, + doenetML, }, "*", ); @@ -317,10592 +214,44 @@ describe("Math Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x+z"); - }); - - cy.get(cesc2("#/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x+z"); - }); - }); - - it("point adapts into a math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 - 2 + $_point1 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eq(5); - // expect(stateVariables['/_math1'].activeChildren[1].componentName).equal(coords.componentName); - // expect(coords.adaptedFrom.componentName).eq(point.componentName); - }); - }); - - it("adjacent string children in math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 23 - - ($_math1, 3) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren[0]).eq("2"); - expect(stateVariables["/_math1"].activeChildren[1]).eq("3"); - expect(stateVariables["/_math1"].stateValues.value).eq(6); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(6); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(3); - }); - - cy.log("Move point to (7,9)"); - cy.window().then(async (win) => { - console.log(`move point1`); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 7, y: 9 }, - }); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - // Since we mark the component to ignore changes to defining children, - // the activeChildren might not be changed - // expect(stateVariables["/_math1"].activeChildren[0]).eq("7"); - // expect(stateVariables["/_math1"].activeChildren[1]).eq(""); - expect(stateVariables["/_math1"].stateValues.value).eq(7); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(7); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(9); - }); - }); - - it("math displayed rounded to 3 significant digits by default", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

1.001

-

0.3004 x + 4pi

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0.3x+4Ο€"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eq(1.001); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "+", - ["*", 0.3004, "x"], - ["*", 4, "pi"], - ]); - }); - }); - - it("mutual references of format", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - q -

- \\sin(y) - - sin(x) - -

-

- sin(u) - - \\sin(v) - -

- - - - -

-

-

-

- - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "q"); // to wait to load - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)sin(y)"); - }); - cy.get(cesc("#\\/b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(u)sin(v)"); - }); - - cy.get(cesc("#\\/formata")).should("have.text", "latex"); - cy.get(cesc("#\\/formatb")).should("have.text", "text"); - cy.get(cesc("#\\/formatc")).should("have.text", "text"); - cy.get(cesc("#\\/formatd")).should("have.text", "latex"); - - cy.log("change format of second to latex"); - cy.get(cesc("#\\/_textinput2_input")).clear().type(`latex{enter}`); - - cy.get(cesc("#\\/a")).should("contain.text", "insxsin(y)"); - cy.get(cesc("#\\/a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("insxsin(y)"); - }); - cy.get(cesc("#\\/b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("insusin(v)"); - }); - - cy.get(cesc("#\\/formata")).should("have.text", "latex"); - cy.get(cesc("#\\/formatb")).should("have.text", "latex"); - cy.get(cesc("#\\/formatc")).should("have.text", "latex"); - cy.get(cesc("#\\/formatd")).should("have.text", "latex"); - - cy.log("change format of first to text"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`text{enter}`); - - cy.get(cesc("#\\/a")).should("contain.text", "οΌΏ"); - cy.get(cesc("#\\/a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sinuοΌΏ"); - }); - - cy.get(cesc("#\\/formata")).should("have.text", "text"); - cy.get(cesc("#\\/formatb")).should("have.text", "latex"); - cy.get(cesc("#\\/formatc")).should("have.text", "latex"); - cy.get(cesc("#\\/formatd")).should("have.text", "text"); - - cy.log("change format of second back to text"); - cy.get(cesc("#\\/_textinput2_input")).clear().type(`text{enter}`); - - cy.get(cesc("#\\/b")).should("contain.text", "sin(u)οΌΏ"); - - cy.get(cesc("#\\/a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(u)οΌΏ"); - }); - - cy.get(cesc("#\\/formata")).should("have.text", "text"); - cy.get(cesc("#\\/formatb")).should("have.text", "text"); - cy.get(cesc("#\\/formatc")).should("have.text", "text"); - cy.get(cesc("#\\/formatd")).should("have.text", "text"); - - cy.log("change format of first back to latext"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`latex{enter}`); - - cy.get(cesc("#\\/a")).should("contain.text", "sin(x)sin(y)"); - - cy.get(cesc("#\\/a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)sin(y)"); - }); - cy.get(cesc("#\\/b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(u)sin(v)"); - }); - - cy.get(cesc("#\\/formata")).should("have.text", "latex"); - cy.get(cesc("#\\/formatb")).should("have.text", "text"); - cy.get(cesc("#\\/formatc")).should("have.text", "text"); - cy.get(cesc("#\\/formatd")).should("have.text", "latex"); - }); - - it("simplify math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

Default is no simplification: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

-

Explicit no simplify: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

-

Full simplify a: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

-

Full simplify b: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

-

Simplify numbers: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

-

Simplify numbers preserve order: 1x^2-3 +0x^2 + 4 -2x^2-3 + 5x^2

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1x2βˆ’3+0x2+4βˆ’2x2βˆ’3+5x2"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1x2βˆ’3+0x2+4βˆ’2x2βˆ’3+5x2"); - }); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4x2βˆ’2"); - }); - cy.get(cesc("#\\/_math4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4x2βˆ’2"); - }); - cy.get(cesc("#\\/_math5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("βˆ’2x2+x2+5x2βˆ’2"); - }); - cy.get(cesc("#\\/_math6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2+1βˆ’2x2βˆ’3+5x2"); - }); - - let originalTree = [ - "+", - ["*", 1, ["^", "x", 2]], - -3, - ["*", 0, ["^", "x", 2]], - 4, - ["-", ["*", 2, ["^", "x", 2]]], - -3, - ["*", 5, ["^", "x", 2]], - ]; - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls( - originalTree, - ); - expect(stateVariables["/_math2"].stateValues.value).eqls( - originalTree, - ); - expect(stateVariables["/_math3"].stateValues.value).eqls([ - "+", - ["*", 4, ["^", "x", 2]], - -2, - ]); - expect(stateVariables["/_math4"].stateValues.value).eqls([ - "+", - ["*", 4, ["^", "x", 2]], - -2, - ]); - expect(stateVariables["/_math5"].stateValues.value).eqls([ - "+", - ["*", -2, ["^", "x", 2]], - ["^", "x", 2], - ["*", 5, ["^", "x", 2]], - -2, - ]); - expect(stateVariables["/_math6"].stateValues.value).eqls([ - "+", - ["^", "x", 2], - 1, - ["*", -2, ["^", "x", 2]], - -3, - ["*", 5, ["^", "x", 2]], - ]); - }); - }); - - it("expand math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

Default is to not expand: (x-3)(2x+4)

-

Expand: (x-3)(2x+4)

-

Don't expand sum: (x-3)(2x+4) - (3x+5)(7-x)

-

Expand: (x-3)(2x+4) - (3x+5)(7-x)

-

Expand: 2(1-x)(1+x)(-2)

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(xβˆ’3)(2x+4)"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x2βˆ’2xβˆ’12"); - }); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(xβˆ’3)(2x+4)βˆ’(3x+5)(7βˆ’x)"); - }); - cy.get(cesc("#\\/_math4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5x2βˆ’18xβˆ’47"); - }); - cy.get(cesc("#\\/_math5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4x2βˆ’4"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - ["+", "x", -3], - ["+", ["*", 2, "x"], 4], - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "+", - ["*", 2, ["^", "x", 2]], - ["*", -2, "x"], - -12, - ]); - expect(stateVariables["/_math3"].stateValues.value).eqls([ - "+", - ["*", ["+", "x", -3], ["+", ["*", 2, "x"], 4]], - ["-", ["*", ["+", ["*", 3, "x"], 5], ["+", 7, ["-", "x"]]]], - ]); - expect(stateVariables["/_math4"].stateValues.value).eqls([ - "+", - ["*", 5, ["^", "x", 2]], - ["*", -18, "x"], - -47, - ]); - expect(stateVariables["/_math5"].stateValues.value).eqls([ - "+", - ["*", 4, ["^", "x", 2]], - -4, - ]); - }); - }); - - it("create vectors and intervals", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

Default: (1,2,3),(4,5),[6,7],(8,9],[10,11)

-

Create vectors: (1,2,3),(4,5),[6,7],(8,9],[10,11)

-

Create intervals: (1,2,3),(4,5),[6,7],(8,9],[10,11)

-

Create vectors and intervals: (1,2,3),(4,5),[6,7],(8,9],[10,11)

-

Alt vectors: ⟨1,2,3⟩,⟨4,5⟩,[6,7],(8,9],[10,11)

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Look same in browser (except alt-vector)"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,3),(4,5),[6,7],(8,9],[10,11)"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,3),(4,5),[6,7],(8,9],[10,11)"); - }); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,3),(4,5),[6,7],(8,9],[10,11)"); - }); - cy.get(cesc("#\\/_math4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,3),(4,5),[6,7],(8,9],[10,11)"); - }); - cy.get(cesc("#\\/_math5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("⟨1,2,3⟩,⟨4,5⟩,[6,7],(8,9],[10,11)"); - }); - - cy.log("Different internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "list", - ["tuple", 1, 2, 3], - ["tuple", 4, 5], - ["array", 6, 7], - ["interval", ["tuple", 8, 9], ["tuple", false, true]], - ["interval", ["tuple", 10, 11], ["tuple", true, false]], - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "list", - ["vector", 1, 2, 3], - ["vector", 4, 5], - ["array", 6, 7], - ["interval", ["tuple", 8, 9], ["tuple", false, true]], - ["interval", ["tuple", 10, 11], ["tuple", true, false]], - ]); - expect(stateVariables["/_math3"].stateValues.value).eqls([ - "list", - ["tuple", 1, 2, 3], - ["interval", ["tuple", 4, 5], ["tuple", false, false]], - ["interval", ["tuple", 6, 7], ["tuple", true, true]], - ["interval", ["tuple", 8, 9], ["tuple", false, true]], - ["interval", ["tuple", 10, 11], ["tuple", true, false]], - ]); - expect(stateVariables["/_math4"].stateValues.value).eqls([ - "list", - ["vector", 1, 2, 3], - ["vector", 4, 5], - ["interval", ["tuple", 6, 7], ["tuple", true, true]], - ["interval", ["tuple", 8, 9], ["tuple", false, true]], - ["interval", ["tuple", 10, 11], ["tuple", true, false]], - ]); - expect(stateVariables["/_math5"].stateValues.value).eqls([ - "list", - ["altvector", 1, 2, 3], - ["altvector", 4, 5], - ["array", 6, 7], - ["interval", ["tuple", 8, 9], ["tuple", false, true]], - ["interval", ["tuple", 10, 11], ["tuple", true, false]], - ]); - }); - }); - - it("display small numbers as zero by default", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

2x + (1E-15)y

-

2x + (1E-15)y

-

2x + (1E-13)y

-

2x + (1E-13)y

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x+1β‹…10βˆ’15y"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x+0y"); - }); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x+1β‹…10βˆ’13y"); - }); - cy.get(cesc("#\\/_math4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x+0y"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["*", 1e-15, "y"], - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["*", 1e-15, "y"], - ]); - expect(stateVariables["/_math3"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["*", 1e-13, "y"], - ]); - expect(stateVariables["/_math4"].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - ["*", 1e-13, "y"], - ]); - expect(stateVariables["/_math1"].stateValues.displaySmallAsZero).eq( - 0, - ); - expect(stateVariables["/_math2"].stateValues.displaySmallAsZero).eq( - 1e-14, - ); - expect(stateVariables["/_math3"].stateValues.displaySmallAsZero).eq( - 1e-14, - ); - expect(stateVariables["/_math4"].stateValues.displaySmallAsZero).eq( - 1e-12, - ); - }); - }); - - it("display digits and decimals", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

621802.3520303639164826281

-

31.3835205397397634 x + 4pi

-

621802.3520303639164826281

-

31.3835205397397634 x + 4pi

-

621802.3520303639164826281

-

31.3835205397397634 x + 4pi

-

$expr1{name="expr1Dig5a" displayDigits="5"}

-

$expr2{name="expr2Dig5a" displayDigits="5"}

-

$expr1{name="expr1Dec5a" displayDecimals="5"}

-

$expr2{name="expr2Dec5a" displayDecimals="5"}

-

$expr1Dec5{name="expr1Dig5b" displayDigits="5"}

-

$expr2Dec5{name="expr2Dig5b" displayDigits="5"}

-

$expr1Dig5{name="expr1Dec5b" displayDecimals="5"}

-

$expr2Dig5{name="expr2Dec5b" displayDecimals="5"}

-

$expr1Dec5a{name="expr1Dig5c" displayDigits="5"}

-

$expr2Dec5a{name="expr2Dig5c" displayDigits="5"}

-

$expr1Dig5a{name="expr1Dec5c" displayDecimals="5"}

-

$expr2Dig5a{name="expr2Dec5c" displayDecimals="5"}

-

$expr1Dec5b{name="expr1Dig5d" displayDigits="5"}

-

$expr2Dec5b{name="expr2Dig5d" displayDigits="5"}

-

$expr1Dig5b{name="expr1Dec5d" displayDecimals="5"}

-

$expr2Dig5b{name="expr2Dec5d" displayDecimals="5"}

- -

$expr1{name="expr1Dig5Dec1" displayDigits="5" displayDecimals="1"}

-

$expr2{name="expr2Dig5Dec1" displayDigits="5" displayDecimals="1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/expr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35"); - }); - cy.get(cesc("#\\/expr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dig5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621800"); - }); - cy.get(cesc("#\\/expr2Dig5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.384x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dec5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dig5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621800"); - }); - cy.get(cesc("#\\/expr2Dig5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.384x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dec5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352x+4Ο€"); - }); - - cy.get(cesc("#\\/expr1Dig5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621800"); - }); - cy.get(cesc("#\\/expr2Dig5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.384x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dec5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352x+4Ο€"); - }); - - cy.get(cesc("#\\/expr1Dig5c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621800"); - }); - cy.get(cesc("#\\/expr2Dig5c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.384x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec5c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dec5c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352x+4Ο€"); - }); - - cy.get(cesc("#\\/expr1Dig5d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621800"); - }); - cy.get(cesc("#\\/expr2Dig5d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.384x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec5d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dec5d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352x+4Ο€"); - }); - - cy.get(cesc("#\\/expr1Dig5Dec1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.4"); - }); - cy.get(cesc("#\\/expr2Dig5Dec1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.384x+4Ο€"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/expr1"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig5"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec5"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec5"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5a"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig5a"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec5a"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec5a"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5b"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig5b"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec5b"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec5b"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5c"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig5c"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec5c"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec5c"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5d"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig5d"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec5d"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec5d"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5Dec1"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig5Dec1"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - - expect(stateVariables["/expr1"].stateValues.valueForDisplay).eq( - 621802.35, - ); - expect(stateVariables["/expr2"].stateValues.valueForDisplay).eqls([ - "+", - ["*", 31.38, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5"].stateValues.valueForDisplay).eq( - 621800, - ); - expect( - stateVariables["/expr2Dig5"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); - expect(stateVariables["/expr1Dec5"].stateValues.valueForDisplay).eq( - 621802.35203, - ); - expect( - stateVariables["/expr2Dec5"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig5a"].stateValues.valueForDisplay, - ).eq(621800); - expect( - stateVariables["/expr2Dig5a"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dec5a"].stateValues.valueForDisplay, - ).eq(621802.35203); - expect( - stateVariables["/expr2Dec5a"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig5b"].stateValues.valueForDisplay, - ).eq(621800); - expect( - stateVariables["/expr2Dig5b"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dec5b"].stateValues.valueForDisplay, - ).eq(621802.35203); - expect( - stateVariables["/expr2Dec5b"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig5c"].stateValues.valueForDisplay, - ).eq(621800); - expect( - stateVariables["/expr2Dig5c"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dec5c"].stateValues.valueForDisplay, - ).eq(621802.35203); - expect( - stateVariables["/expr2Dec5c"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig5d"].stateValues.valueForDisplay, - ).eq(621800); - expect( - stateVariables["/expr2Dig5d"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dec5d"].stateValues.valueForDisplay, - ).eq(621802.35203); - expect( - stateVariables["/expr2Dec5d"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig5Dec1"].stateValues.valueForDisplay, - ).eq(621802.4); - expect( - stateVariables["/expr2Dig5Dec1"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); - }); - }); - - it("display digits and decimals 2", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

621802.3520303639164826281

-

31.3835205397397634 x + 4pi

-

621802.3520303639164826281

-

31.3835205397397634 x + 4pi

-

621802.3520303639164826281

-

31.3835205397397634 x + 4pi

-

$expr1{name="expr1Dig5a" displayDigits="5"}

-

$expr2{name="expr2Dig5a" displayDigits="5"}

-

$expr1{name="expr1Dec5a" displayDecimals="5"}

-

$expr2{name="expr2Dec5a" displayDecimals="5"}

-

$expr1Dec5{name="expr1Dig8Dec5" displayDigits="8" displayDecimals="5"}

-

$expr2Dec5{name="expr2Dig8Dec5" displayDigits="8" displayDecimals="5"}

-

$expr1Dig5{name="expr1Dec8Dig5" displayDigits="5" displayDecimals="8"}

-

$expr2Dig5{name="expr2Dec8Dig5" displayDigits="5" displayDecimals="8"}

-

$expr1Dec5a{name="expr1Dig8Dec5a" displayDigits="8" displayDecimals="5"}

-

$expr2Dec5a{name="expr2Dig8Dec5a" displayDigits="8" displayDecimals="5"}

-

$expr1Dig5a{name="expr1Dec8Dig5a" displayDigits="5" displayDecimals="8"}

-

$expr2Dig5a{name="expr2Dec8Dig5a" displayDigits="5" displayDecimals="8"}

-

$expr1Dec8Dig5{name="expr1Dig3Dec8" displayDigits="3" displayDecimals="8"}

-

$expr2Dec8Dig5{name="expr2Dig3Dec8" displayDigits="3" displayDecimals="8"}

-

$expr1Dig8Dec5{name="expr1Dec3Dig8" displayDigits="8" displayDecimals="3"}

-

$expr2Dig8Dec5{name="expr2Dec3Dig8" displayDigits="8" displayDecimals="3"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/expr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35"); - }); - cy.get(cesc("#\\/expr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dig5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621800"); - }); - cy.get(cesc("#\\/expr2Dig5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.384x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dec5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dig5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621800"); - }); - cy.get(cesc("#\\/expr2Dig5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.384x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dec5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352x+4Ο€"); - }); - - cy.get(cesc("#\\/expr1Dig8Dec5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dig8Dec5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.383521x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec8Dig5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203036"); - }); - cy.get(cesc("#\\/expr2Dec8Dig5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352054x+4Ο€"); - }); - - cy.get(cesc("#\\/expr1Dig8Dec5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203"); - }); - cy.get(cesc("#\\/expr2Dig8Dec5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.383521x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec8Dig5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203036"); - }); - cy.get(cesc("#\\/expr2Dec8Dig5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352054x+4Ο€"); - }); - - cy.get(cesc("#\\/expr1Dig3Dec8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.35203036"); - }); - cy.get(cesc("#\\/expr2Dig3Dec8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.38352054x+4Ο€"); - }); - cy.get(cesc("#\\/expr1Dec3Dig8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("621802.352"); - }); - cy.get(cesc("#\\/expr2Dec3Dig8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("31.383521x+4Ο€"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/expr1"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig5"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec5"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec5"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5a"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig5a"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec5a"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec5a"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig8Dec5"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig8Dec5"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec8Dig5"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec8Dig5"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig8Dec5a"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig8Dec5a"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec8Dig5a"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec8Dig5a"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig3Dec8"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dig3Dec8"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dec3Dig8"].stateValues.value).eq( - 621802.3520303639, - ); - expect(stateVariables["/expr2Dec3Dig8"].stateValues.value).eqls([ - "+", - ["*", 31.383520539739763, "x"], - ["*", 4, "pi"], - ]); - - expect(stateVariables["/expr1"].stateValues.valueForDisplay).eq( - 621802.35, - ); - expect(stateVariables["/expr2"].stateValues.valueForDisplay).eqls([ - "+", - ["*", 31.38, "x"], - ["*", 4, "pi"], - ]); - expect(stateVariables["/expr1Dig5"].stateValues.valueForDisplay).eq( - 621800, - ); - expect( - stateVariables["/expr2Dig5"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); - expect(stateVariables["/expr1Dec5"].stateValues.valueForDisplay).eq( - 621802.35203, - ); - expect( - stateVariables["/expr2Dec5"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig5a"].stateValues.valueForDisplay, - ).eq(621800); - expect( - stateVariables["/expr2Dig5a"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.384, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dec5a"].stateValues.valueForDisplay, - ).eq(621802.35203); - expect( - stateVariables["/expr2Dec5a"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig8Dec5"].stateValues.valueForDisplay, - ).eq(621802.35203); - expect( - stateVariables["/expr2Dig8Dec5"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.383521, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dec8Dig5"].stateValues.valueForDisplay, - ).eq(621802.35203036); - expect( - stateVariables["/expr2Dec8Dig5"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352054, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig8Dec5a"].stateValues.valueForDisplay, - ).eq(621802.35203); - expect( - stateVariables["/expr2Dig8Dec5a"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.383521, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dec8Dig5a"].stateValues.valueForDisplay, - ).eq(621802.35203036); - expect( - stateVariables["/expr2Dec8Dig5a"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352054, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dig3Dec8"].stateValues.valueForDisplay, - ).eq(621802.35203036); - expect( - stateVariables["/expr2Dig3Dec8"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.38352054, "x"], ["*", 4, "pi"]]); - expect( - stateVariables["/expr1Dec3Dig8"].stateValues.valueForDisplay, - ).eq(621802.352); - expect( - stateVariables["/expr2Dec3Dig8"].stateValues.valueForDisplay, - ).eqls(["+", ["*", 31.383521, "x"], ["*", 4, "pi"]]); - }); - }); - - it("pad zeros with display digits and decimals", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

62.1

-

162.1*10^(-3)

-

1.3 x + 4pi

-

$_math1{name="dig5a" displayDigits="5"}

-

$_math1{name="dig5apad" displayDigits="5" padZeros}

-

$_math2{name="dig5b" displayDigits="5"}

-

$_math2{name="dig5bpad" displayDigits="5" padZeros}

-

$_math3{name="dig5c" displayDigits="5"}

-

$_math3{name="dig5cpad" displayDigits="5" padZeros}

-

$_math1{name="dec5a" displayDecimals="5"}

-

$_math1{name="dec5apad" displayDecimals="5" padZeros}

-

$_math2{name="dec5b" displayDecimals="5"}

-

$_math2{name="dec5bpad" displayDecimals="5" padZeros}

-

$_math3{name="dec5c" displayDecimals="5"}

-

$_math3{name="dec5cpad" displayDecimals="5" padZeros}

-

$_math1{name="dig5dec1a" displayDigits="5" displayDecimals="1"}

-

$_math1{name="dig5dec1apad" displayDigits="5" displayDecimals="1" padZeros}

-

$_math2{name="dig5dec1b" displayDigits="5" displayDecimals="1"}

-

$_math2{name="dig5dec1bpad" displayDigits="5" displayDecimals="1" padZeros}

-

$_math3{name="dig5dec1c" displayDigits="5" displayDecimals="1"}

-

$_math3{name="dig5dec1cpad" displayDigits="5" displayDecimals="1" padZeros}

- -

$dig5a.text{assignNames="dig5aText"}

-

$dig5apad.text{assignNames="dig5apadText"}

-

$dig5b.text{assignNames="dig5bText"}

-

$dig5bpad.text{assignNames="dig5bpadText"}

-

$dig5c.text{assignNames="dig5cText"}

-

$dig5cpad.text{assignNames="dig5cpadText"}

-

$dec5a.text{assignNames="dec5aText"}

-

$dec5apad.text{assignNames="dec5apadText"}

-

$dec5b.text{assignNames="dec5bText"}

-

$dec5bpad.text{assignNames="dec5bpadText"}

-

$dec5c.text{assignNames="dec5cText"}

-

$dec5cpad.text{assignNames="dec5cpadText"}

-

$dig5dec1a.text{assignNames="dig5dec1aText"}

-

$dig5dec1apad.text{assignNames="dig5dec1apadText"}

-

$dig5dec1b.text{assignNames="dig5dec1bText"}

-

$dig5dec1bpad.text{assignNames="dig5dec1bpadText"}

-

$dig5dec1c.text{assignNames="dig5dec1cText"}

-

$dig5dec1cpad.text{assignNames="dig5dec1cpadText"}

- -

$dig5a.value{assignNames="dig5aValue"}

-

$dig5apad.value{assignNames="dig5apadValue"}

-

$dig5b.value{assignNames="dig5bValue"}

-

$dig5bpad.value{assignNames="dig5bpadValue"}

-

$dig5c.value{assignNames="dig5cValue"}

-

$dig5cpad.value{assignNames="dig5cpadValue"}

-

$dec5a.value{assignNames="dec5aValue"}

-

$dec5apad.value{assignNames="dec5apadValue"}

-

$dec5b.value{assignNames="dec5bValue"}

-

$dec5bpad.value{assignNames="dec5bpadValue"}

-

$dec5c.value{assignNames="dec5cValue"}

-

$dec5cpad.value{assignNames="dec5cpadValue"}

-

$dig5dec1a.value{assignNames="dig5dec1aValue"}

-

$dig5dec1apad.value{assignNames="dig5dec1apadValue"}

-

$dig5dec1b.value{assignNames="dig5dec1bValue"}

-

$dig5dec1bpad.value{assignNames="dig5dec1bpadValue"}

-

$dig5dec1c.value{assignNames="dig5dec1cValue"}

-

$dig5dec1cpad.value{assignNames="dig5dec1cpadValue"}

- -

$dig5a.number{assignNames="dig5aNumber"}

-

$dig5apad.number{assignNames="dig5apadNumber"}

-

$dig5b.number{assignNames="dig5bNumber"}

-

$dig5bpad.number{assignNames="dig5bpadNumber"}

-

$dig5c.number{assignNames="dig5cNumber"}

-

$dig5cpad.number{assignNames="dig5cpadNumber"}

-

$dec5a.number{assignNames="dec5aNumber"}

-

$dec5apad.number{assignNames="dec5apadNumber"}

-

$dec5b.number{assignNames="dec5bNumber"}

-

$dec5bpad.number{assignNames="dec5bpadNumber"}

-

$dec5c.number{assignNames="dec5cNumber"}

-

$dec5cpad.number{assignNames="dec5cpadNumber"}

-

$dig5dec1a.number{assignNames="dig5dec1aNumber"}

-

$dig5dec1apad.number{assignNames="dig5dec1apadNumber"}

-

$dig5dec1b.number{assignNames="dig5dec1bNumber"}

-

$dig5dec1bpad.number{assignNames="dig5dec1bpadNumber"}

-

$dig5dec1c.number{assignNames="dig5dec1cNumber"}

-

$dig5dec1cpad.number{assignNames="dig5dec1cpadNumber"}

- -

$dig5a

-

$dig5apad

-

$dig5b

-

$dig5bpad

-

$dig5c

-

$dig5cpad

-

$dec5a

-

$dec5apad

-

$dec5b

-

$dec5bpad

-

$dec5c

-

$dec5cpad

-

$dig5dec1a

-

$dig5dec1apad

-

$dig5dec1b

-

$dig5dec1bpad

-

$dig5dec1c

-

$dig5dec1cpad

- -

$dig5a

-

$dig5apad

-

$dig5b

-

$dig5bpad

-

$dig5c

-

$dig5cpad

-

$dec5a

-

$dec5apad

-

$dec5b

-

$dec5bpad

-

$dec5c

-

$dec5cpad

-

$dig5dec1a

-

$dig5dec1apad

-

$dig5dec1b

-

$dig5dec1bpad

-

$dig5dec1c

-

$dig5dec1cpad

- -

$dig5a.x1{assignNames="dig5aX1"}

-

$dig5apad.x1{assignNames="dig5apadX1"}

-

$dig5b.x1{assignNames="dig5bX1"}

-

$dig5bpad.x1{assignNames="dig5bpadX1"}

-

$dig5c.x1{assignNames="dig5cX1"}

-

$dig5cpad.x1{assignNames="dig5cpadX1"}

-

$dec5a.x1{assignNames="dec5aX1"}

-

$dec5apad.x1{assignNames="dec5apadX1"}

-

$dec5b.x1{assignNames="dec5bX1"}

-

$dec5bpad.x1{assignNames="dec5bpadX1"}

-

$dec5c.x1{assignNames="dec5cX1"}

-

$dec5cpad.x1{assignNames="dec5cpadX1"}

-

$dig5dec1a.x1{assignNames="dig5dec1aX1"}

-

$dig5dec1apad.x1{assignNames="dig5dec1apadX1"}

-

$dig5dec1b.x1{assignNames="dig5dec1bX1"}

-

$dig5dec1bpad.x1{assignNames="dig5dec1bpadX1"}

-

$dig5dec1c.x1{assignNames="dig5dec1cX1"}

-

$dig5dec1cpad.x1{assignNames="dig5dec1cpadX1"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - - cy.get(cesc("#\\/dig5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dig5apad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.100"); - }); - cy.get(cesc("#\\/dig5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5bpad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dig5cpad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3000x+4.0000Ο€"); - }); - cy.get(cesc("#\\/dec5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dec5apad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.10000"); - }); - cy.get(cesc("#\\/dec5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dec5bpad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10000β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dec5c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dec5cpad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.30000x+4.00000Ο€"); - }); - cy.get(cesc("#\\/dig5dec1a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dig5dec1apad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.100"); - }); - cy.get(cesc("#\\/dig5dec1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5dec1bpad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5dec1c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dig5dec1cpad")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3000x+4.0000Ο€"); - }); - - cy.get(cesc("#\\/dig5aText")).should("have.text", "62.1"); - cy.get(cesc("#\\/dig5apadText")).should("have.text", "62.100"); - cy.get(cesc("#\\/dig5bText")).should("have.text", "162.1 * 10⁻³"); - cy.get(cesc("#\\/dig5bpadText")).should("have.text", "162.10 * 10⁻³"); - cy.get(cesc("#\\/dig5cText")).should("have.text", "1.3 x + 4 Ο€"); - cy.get(cesc("#\\/dig5cpadText")).should( - "have.text", - "1.3000 x + 4.0000 Ο€", - ); - cy.get(cesc("#\\/dec5aText")).should("have.text", "62.1"); - cy.get(cesc("#\\/dec5apadText")).should("have.text", "62.10000"); - cy.get(cesc("#\\/dec5bText")).should("have.text", "162.1 * 10⁻³"); - cy.get(cesc("#\\/dec5bpadText")).should( - "have.text", - "162.10000 * 10⁻³", - ); - cy.get(cesc("#\\/dec5cText")).should("have.text", "1.3 x + 4 Ο€"); - cy.get(cesc("#\\/dec5cpadText")).should( - "have.text", - "1.30000 x + 4.00000 Ο€", - ); - cy.get(cesc("#\\/dig5dec1aText")).should("have.text", "62.1"); - cy.get(cesc("#\\/dig5dec1apadText")).should("have.text", "62.100"); - cy.get(cesc("#\\/dig5dec1bText")).should("have.text", "162.1 * 10⁻³"); - cy.get(cesc("#\\/dig5dec1bpadText")).should( - "have.text", - "162.10 * 10⁻³", - ); - cy.get(cesc("#\\/dig5dec1cText")).should("have.text", "1.3 x + 4 Ο€"); - cy.get(cesc("#\\/dig5dec1cpadText")).should( - "have.text", - "1.3000 x + 4.0000 Ο€", - ); - - cy.get(cesc("#\\/dig5aValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dig5apadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.100"); - }); - cy.get(cesc("#\\/dig5bValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5bpadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5cValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dig5cpadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3000x+4.0000Ο€"); - }); - cy.get(cesc("#\\/dec5aValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dec5apadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.10000"); - }); - cy.get(cesc("#\\/dec5bValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dec5bpadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10000β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dec5cValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dec5cpadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.30000x+4.00000Ο€"); - }); - cy.get(cesc("#\\/dig5dec1aValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dig5dec1apadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.100"); - }); - cy.get(cesc("#\\/dig5dec1bValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5dec1bpadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5dec1cValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dig5dec1cpadValue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3000x+4.0000Ο€"); - }); - - cy.get(cesc("#\\/dig5aNumber")).should("have.text", "62.1"); - cy.get(cesc("#\\/dig5apadNumber")).should("have.text", "62.100"); - cy.get(cesc("#\\/dig5bNumber")).should("have.text", "0.1621"); - cy.get(cesc("#\\/dig5bpadNumber")).should("have.text", "0.16210"); - cy.get(cesc("#\\/dig5cNumber")).should("have.text", "NaN"); - cy.get(cesc("#\\/dig5cpadNumber")).should("have.text", "NaN"); - cy.get(cesc("#\\/dec5aNumber")).should("have.text", "62.1"); - cy.get(cesc("#\\/dec5apadNumber")).should("have.text", "62.10000"); - cy.get(cesc("#\\/dec5bNumber")).should("have.text", "0.1621"); - cy.get(cesc("#\\/dec5bpadNumber")).should("have.text", "0.16210"); - cy.get(cesc("#\\/dec5cNumber")).should("have.text", "NaN"); - cy.get(cesc("#\\/dec5cpadNumber")).should("have.text", "NaN"); - cy.get(cesc("#\\/dig5dec1aNumber")).should("have.text", "62.1"); - cy.get(cesc("#\\/dig5dec1apadNumber")).should("have.text", "62.100"); - cy.get(cesc("#\\/dig5dec1bNumber")).should("have.text", "0.1621"); - cy.get(cesc("#\\/dig5dec1bpadNumber")).should("have.text", "0.16210"); - cy.get(cesc("#\\/dig5dec1cNumber")).should("have.text", "NaN"); - cy.get(cesc("#\\/dig5dec1cpadNumber")).should("have.text", "NaN"); - - cy.get(cesc("#\\/dig5aMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dig5apadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.100"); - }); - cy.get(cesc("#\\/dig5bMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5bpadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5cMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dig5cpadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3000x+4.0000Ο€"); - }); - cy.get(cesc("#\\/dec5aMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dec5apadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.10000"); - }); - cy.get(cesc("#\\/dec5bMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dec5bpadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10000β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dec5cMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dec5cpadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.30000x+4.00000Ο€"); - }); - cy.get(cesc("#\\/dig5dec1aMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dig5dec1apadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.100"); - }); - cy.get(cesc("#\\/dig5dec1bMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5dec1bpadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5dec1cMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dig5dec1cpadMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3000x+4.0000Ο€"); - }); - - cy.get(cesc("#\\/dig5aNumber2")).should("have.text", "62.1"); - cy.get(cesc("#\\/dig5apadNumber2")).should("have.text", "62.100"); - cy.get(cesc("#\\/dig5bNumber2")).should("have.text", "0.1621"); - cy.get(cesc("#\\/dig5bpadNumber2")).should("have.text", "0.16210"); - cy.get(cesc("#\\/dig5cNumber2")).should("have.text", "NaN"); - cy.get(cesc("#\\/dig5cpadNumber2")).should("have.text", "NaN"); - cy.get(cesc("#\\/dec5aNumber2")).should("have.text", "62.1"); - cy.get(cesc("#\\/dec5apadNumber2")).should("have.text", "62.10000"); - cy.get(cesc("#\\/dec5bNumber2")).should("have.text", "0.1621"); - cy.get(cesc("#\\/dec5bpadNumber2")).should("have.text", "0.16210"); - cy.get(cesc("#\\/dec5cNumber2")).should("have.text", "NaN"); - cy.get(cesc("#\\/dec5cpadNumber2")).should("have.text", "NaN"); - cy.get(cesc("#\\/dig5dec1aNumber2")).should("have.text", "62.1"); - cy.get(cesc("#\\/dig5dec1apadNumber2")).should("have.text", "62.100"); - cy.get(cesc("#\\/dig5dec1bNumber2")).should("have.text", "0.1621"); - cy.get(cesc("#\\/dig5dec1bpadNumber2")).should("have.text", "0.16210"); - cy.get(cesc("#\\/dig5dec1cNumber2")).should("have.text", "NaN"); - cy.get(cesc("#\\/dig5dec1cpadNumber2")).should("have.text", "NaN"); - - cy.get(cesc("#\\/dig5aX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dig5apadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.100"); - }); - cy.get(cesc("#\\/dig5bX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5bpadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5cX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dig5cpadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3000x+4.0000Ο€"); - }); - cy.get(cesc("#\\/dec5aX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dec5apadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.10000"); - }); - cy.get(cesc("#\\/dec5bX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dec5bpadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10000β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dec5cX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dec5cpadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.30000x+4.00000Ο€"); - }); - cy.get(cesc("#\\/dig5dec1aX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.1"); - }); - cy.get(cesc("#\\/dig5dec1apadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.100"); - }); - cy.get(cesc("#\\/dig5dec1bX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.1β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5dec1bpadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("162.10β‹…10βˆ’3"); - }); - cy.get(cesc("#\\/dig5dec1cX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3x+4Ο€"); - }); - cy.get(cesc("#\\/dig5dec1cpadX1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1.3000x+4.0000Ο€"); - }); - }); - - it("dynamic rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number: 35203423.02352343201

-

Number of digits:

-

Number of decimals:

-

$n{displayDigits='$ndigits' displayDecimals='$ndecimals' name="na"}

-

$ndigits.value{assignNames="ndigits2"}

-

$ndecimals.value{assignNames="ndecimals2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("35203423.02"); - }); - - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("35203423.024"); - }); - - cy.log("higher decimals"); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/ndecimals2")).should("contain.text", "5"); - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("35203423.02352"); - }); - - cy.log("lower decimals"); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}-3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/ndecimals2")).should("contain.text", "βˆ’3"); - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("35203000"); - }); - - cy.log("increase digits"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}12{enter}", - { force: true }, - ); - cy.get(cesc("#\\/ndigits2")).should("contain.text", "12"); - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("35203423.0235"); - }); - - cy.log("invalid ndigits, falls back to decimals"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/ndigits2")).should("contain.text", "x"); - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("35203000"); - }); - - cy.log("invalid both, no rounding"); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/ndecimals2")).should("contain.text", "y"); - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("35203423.023523435"); - }); - - cy.log("only invalid ndecimals, falls back to digits"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}{backspace}1{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("40000000"); - }); - - cy.log("negative decimals past number magnitude"); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}-8{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/ndecimals2")).should("contain.text", "βˆ’8"); - - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("40000000"); - }); - - cy.log("becomes zero with no digits"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.log("get number back with less rounding"); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}6{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/ndecimals2")).should("contain.text", "βˆ’6"); - - cy.get(cesc("#\\/na")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("35000000"); - }); - }); - - it("function symbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

f(x)

-

g(t)

-

h(z)

-

f(x)

-

g(t)

-

h(z)

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("g(t)"); - }); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hz"); - }); - cy.get(cesc("#\\/_math4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("fx"); - }); - cy.get(cesc("#\\/_math5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("g(t)"); - }); - cy.get(cesc("#\\/_math6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(z)"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "apply", - "f", - "x", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "apply", - "g", - "t", - ]); - expect(stateVariables["/_math3"].stateValues.value).eqls([ - "*", - "h", - "z", - ]); - expect(stateVariables["/_math4"].stateValues.value).eqls([ - "*", - "f", - "x", - ]); - expect(stateVariables["/_math5"].stateValues.value).eqls([ - "apply", - "g", - "t", - ]); - expect(stateVariables["/_math6"].stateValues.value).eqls([ - "apply", - "h", - "z", - ]); - }); - }); - - it("copy and overwrite function symbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- f(x)+m(x) - $m1{functionSymbols="m" name="m2"} - $m2{functionSymbols="m f" name="m3"} - - f(x)+m(x) - $m4{functionSymbols="m" name="m5"} - $m5{functionSymbols="f" name="m6"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)+mx"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("fx+m(x)"); - }); - cy.get(cesc("#\\/m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)+m(x)"); - }); - cy.get(cesc("#\\/m4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)+m(x)"); - }); - cy.get(cesc("#\\/m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("fx+m(x)"); - }); - cy.get(cesc("#\\/m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)+mx"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls([ - "+", - ["apply", "f", "x"], - ["*", "m", "x"], - ]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "+", - ["*", "f", "x"], - ["apply", "m", "x"], - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "+", - ["apply", "f", "x"], - ["apply", "m", "x"], - ]); - expect(stateVariables["/m4"].stateValues.value).eqls([ - "+", - ["apply", "f", "x"], - ["apply", "m", "x"], - ]); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "+", - ["*", "f", "x"], - ["apply", "m", "x"], - ]); - expect(stateVariables["/m6"].stateValues.value).eqls([ - "+", - ["apply", "f", "x"], - ["*", "m", "x"], - ]); - }); - }); - - it("sourcesAreFunctionSymbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

-

- -

$f($x)

-

$x($f)

-

$f($x)

-

$x($f)

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = stateVariables["/f"].stateValues.value; - let x = stateVariables["/x"].stateValues.value; - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${f}${x}`); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${x}${f}`); - }); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${f}(${x})`); - }); - cy.get(cesc("#\\/_math4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${x}${f}`); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - f, - x, - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "*", - x, - f, - ]); - expect(stateVariables["/_math3"].stateValues.value).eqls([ - "apply", - f, - x, - ]); - expect(stateVariables["/_math4"].stateValues.value).eqls([ - "*", - x, - f, - ]); - }); - }); - }); - - it("copy and overwrite sourcesAreFunctionSymbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

- -

$f(x)

-

$m1{sourcesAreFunctionSymbols="f" name="m2"}

-

$m2{sourcesAreFunctionSymbols="" name="m3"}

- -

$f(x)

-

$m4{sourcesAreFunctionSymbols="" name="m5"}

-

$m5{sourcesAreFunctionSymbols="f" name="m6"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = stateVariables["/f"].stateValues.value; - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${f}x`); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${f}(x)`); - }); - cy.get(cesc("#\\/m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${f}x`); - }); - cy.get(cesc("#\\/m4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${f}(x)`); - }); - cy.get(cesc("#\\/m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${f}x`); - }); - cy.get(cesc("#\\/m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${f}(x)`); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls([ - "*", - f, - "x", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "apply", - f, - "x", - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "*", - f, - "x", - ]); - expect(stateVariables["/m4"].stateValues.value).eqls([ - "apply", - f, - "x", - ]); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "*", - f, - "x", - ]); - expect(stateVariables["/m6"].stateValues.value).eqls([ - "apply", - f, - "x", - ]); - }); - }); - }); - - it("copy and overwrite simplify", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

x+x

-

$m1{simplify name="m2"}

-

$m2{simplify="none" name="m3"}

-

$m1.value{simplify assignNames="m2a"}

-

$m2.value{simplify="none" assignNames="m3a"}

- -

x+x

-

$m4{simplify="none" name="m5"}

-

$m5{simplify name="m6"}

-

$m4.value{simplify="none" assignNames="m5a"}

-

$m5a.value{simplify assignNames="m6a"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - cy.get(cesc("#\\/m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x"); - }); - cy.get(cesc("#\\/m2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - cy.get(cesc("#\\/m3a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - cy.get(cesc("#\\/m4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - cy.get(cesc("#\\/m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x"); - }); - cy.get(cesc("#\\/m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - cy.get(cesc("#\\/m5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - cy.get(cesc("#\\/m6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables["/m2a"].stateValues.value).eqls([ - "*", - 2, - "x", - ]); - expect(stateVariables["/m3a"].stateValues.value).eqls([ - "*", - 2, - "x", - ]); - expect(stateVariables["/m4"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables["/m6"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m5a"].stateValues.value).eqls([ - "*", - 2, - "x", - ]); - expect(stateVariables["/m6a"].stateValues.value).eqls([ - "*", - 2, - "x", - ]); - }); - }); - - it("split symbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

xyz

-

xyz

-

xyz

-

xyx

-

xyx

-

xyx

-

xy_uv

-

x2_2x

-

2x_x2

-

xy uv x2y 2x x2

-

xy_uv

-

x2_2x

-

2x_x2

-

xy uv x2y 2x x2

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yx2"); - }); - cy.get(cesc("#\\/m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyx"); - }); - cy.get(cesc("#\\/m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yx2"); - }); - cy.get(cesc("#\\/m7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/m8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x22x"); - }); - cy.get(cesc("#\\/m9")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xx2"); - }); - cy.get(cesc("#\\/m10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - cy.get(cesc("#\\/m11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/m12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x22x"); - }); - cy.get(cesc("#\\/m13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xx2"); - }); - cy.get(cesc("#\\/m14")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls("xyz"); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m4"].stateValues.value).eqls([ - "*", - "y", - ["^", "x", 2], - ]); - expect(stateVariables["/m5"].stateValues.value).eqls("xyx"); - expect(stateVariables["/m6"].stateValues.value).eqls([ - "*", - "y", - ["^", "x", 2], - ]); - expect(stateVariables["/m7"].stateValues.value).eqls([ - "*", - "x", - ["_", "y", "u"], - "v", - ]); - expect(stateVariables["/m8"].stateValues.value).eqls([ - "*", - ["_", "x2", 2], - "x", - ]); - expect(stateVariables["/m9"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x2"], - ]); - expect(stateVariables["/m10"].stateValues.value).eqls([ - "*", - "x", - "y", - "u", - "v", - "x2y", - 2, - "x", - "x2", - ]); - expect(stateVariables["/m11"].stateValues.value).eqls([ - "_", - "xy", - "uv", - ]); - expect(stateVariables["/m12"].stateValues.value).eqls([ - "*", - ["_", "x2", 2], - "x", - ]); - expect(stateVariables["/m13"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x2"], - ]); - expect(stateVariables["/m14"].stateValues.value).eqls([ - "*", - "xy", - "uv", - "x2y", - 2, - "x", - "x2", - ]); - }); - }); - - it("split symbols, nested", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

xyz

-

xyz

-

xyz

-

xyx

-

xyx

-

xyx

-

xy_uv

-

x2_2x

-

2x_x2

-

xy uv x2y 2x x2

-

xy_uv

-

x2_2x

-

2x_x2

-

xy uv x2y 2x x2

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yx2"); - }); - cy.get(cesc("#\\/m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyx"); - }); - cy.get(cesc("#\\/m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yx2"); - }); - cy.get(cesc("#\\/m7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/m8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x22x"); - }); - cy.get(cesc("#\\/m9")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xx2"); - }); - cy.get(cesc("#\\/m10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - cy.get(cesc("#\\/m11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/m12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x22x"); - }); - cy.get(cesc("#\\/m13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xx2"); - }); - cy.get(cesc("#\\/m14")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls("xyz"); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m4"].stateValues.value).eqls([ - "*", - "y", - ["^", "x", 2], - ]); - expect(stateVariables["/m5"].stateValues.value).eqls("xyx"); - expect(stateVariables["/m6"].stateValues.value).eqls([ - "*", - "y", - ["^", "x", 2], - ]); - expect(stateVariables["/m7"].stateValues.value).eqls([ - "*", - "x", - ["_", "y", "u"], - "v", - ]); - expect(stateVariables["/m8"].stateValues.value).eqls([ - "*", - ["_", "x2", 2], - "x", - ]); - expect(stateVariables["/m9"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x2"], - ]); - expect(stateVariables["/m10"].stateValues.value).eqls([ - "*", - "x", - "y", - "u", - "v", - "x2y", - 2, - "x", - "x2", - ]); - expect(stateVariables["/m11"].stateValues.value).eqls([ - "_", - "xy", - "uv", - ]); - expect(stateVariables["/m12"].stateValues.value).eqls([ - "*", - ["_", "x2", 2], - "x", - ]); - expect(stateVariables["/m13"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x2"], - ]); - expect(stateVariables["/m14"].stateValues.value).eqls([ - "*", - "xy", - "uv", - "x2y", - 2, - "x", - "x2", - ]); - }); - }); - - it("split symbols, latex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

xyz

-

xyz

-

\\operatorname{xyz}

-

\\operatorname{xyz}

-

xyz

-

xyx

-

xyx

-

\\operatorname{xyx}

-

\\operatorname{xyx}

-

xyx

-

xy_uv

-

x2_2x

-

\\operatorname{x2}_2x

-

2x_x2

-

2x_\\operatorname{x2}

-

2x_{x2}

-

xy uv x2y 2x x2

-

xy uv \\operatorname{x2y} 2x \\operatorname{x2}

-

xy_uv

-

\\operatorname{xy}_\\operatorname{uv}

-

\\operatorname{xy}_\\operatorname{uv}

-

x2_2x

-

\\operatorname{x2}_2x

-

2x_x2

-

2x_\\operatorname{x2}

-

xy uv x2y 2x x2

-

\\operatorname{xy} \\operatorname{uv} x2y 2x x2

-

\\operatorname{xy} \\operatorname{uv} x2y 2x x2

-

3^x2

-

3^x2

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m2b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yx2"); - }); - cy.get(cesc("#\\/m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyx"); - }); - cy.get(cesc("#\\/m5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyx"); - }); - cy.get(cesc("#\\/m5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyx"); - }); - cy.get(cesc("#\\/m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yx2"); - }); - cy.get(cesc("#\\/m7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/m8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x22x"); - }); - cy.get(cesc("#\\/m8a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x22x"); - }); - cy.get(cesc("#\\/m9")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xxβ‹…2"); - }); - cy.get(cesc("#\\/m9a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xx2"); - }); - cy.get(cesc("#\\/m9b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xx2"); - }); - cy.get(cesc("#\\/m10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - cy.get(cesc("#\\/m10a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - cy.get(cesc("#\\/m11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/m11a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/m11b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/m12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x22x"); - }); - cy.get(cesc("#\\/m12a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x22x"); - }); - cy.get(cesc("#\\/m13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xx2"); - }); - cy.get(cesc("#\\/m13a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2xx2"); - }); - cy.get(cesc("#\\/m14")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - cy.get(cesc("#\\/m14a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - cy.get(cesc("#\\/m14b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuvx2yβ‹…2xx2"); - }); - cy.get(cesc("#\\/m15")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3xβ‹…2"); - }); - cy.get(cesc("#\\/m15a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x2"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls("xyz"); - expect(stateVariables["/m2a"].stateValues.value).eqls("xyz"); - expect(stateVariables["/m2b"].stateValues.value).eqls("xyz"); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m4"].stateValues.value).eqls([ - "*", - "y", - ["^", "x", 2], - ]); - expect(stateVariables["/m5"].stateValues.value).eqls("xyx"); - expect(stateVariables["/m5a"].stateValues.value).eqls("xyx"); - expect(stateVariables["/m5b"].stateValues.value).eqls("xyx"); - expect(stateVariables["/m6"].stateValues.value).eqls([ - "*", - "y", - ["^", "x", 2], - ]); - expect(stateVariables["/m7"].stateValues.value).eqls([ - "*", - "x", - ["_", "y", "u"], - "v", - ]); - expect(stateVariables["/m8"].stateValues.value).eqls([ - "*", - ["_", "x2", 2], - "x", - ]); - expect(stateVariables["/m8a"].stateValues.value).eqls([ - "*", - ["_", "x2", 2], - "x", - ]); - expect(stateVariables["/m9"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x"], - 2, - ]); - expect(stateVariables["/m9a"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x2"], - ]); - expect(stateVariables["/m9b"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x2"], - ]); - expect(stateVariables["/m10"].stateValues.value).eqls([ - "*", - "x", - "y", - "u", - "v", - "x2y", - 2, - "x", - "x2", - ]); - expect(stateVariables["/m10a"].stateValues.value).eqls([ - "*", - "x", - "y", - "u", - "v", - "x2y", - 2, - "x", - "x2", - ]); - expect(stateVariables["/m11"].stateValues.value).eqls([ - "_", - "xy", - "uv", - ]); - expect(stateVariables["/m11a"].stateValues.value).eqls([ - "_", - "xy", - "uv", - ]); - expect(stateVariables["/m11b"].stateValues.value).eqls([ - "_", - "xy", - "uv", - ]); - expect(stateVariables["/m12"].stateValues.value).eqls([ - "*", - ["_", "x2", 2], - "x", - ]); - expect(stateVariables["/m12a"].stateValues.value).eqls([ - "*", - ["_", "x2", 2], - "x", - ]); - expect(stateVariables["/m13"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x2"], - ]); - expect(stateVariables["/m13a"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", "x2"], - ]); - expect(stateVariables["/m14"].stateValues.value).eqls([ - "*", - "xy", - "uv", - "x2y", - 2, - "x", - "x2", - ]); - expect(stateVariables["/m14a"].stateValues.value).eqls([ - "*", - "xy", - "uv", - "x2y", - 2, - "x", - "x2", - ]); - expect(stateVariables["/m14b"].stateValues.value).eqls([ - "*", - "xy", - "uv", - "x2y", - 2, - "x", - "x2", - ]); - expect(stateVariables["/m15"].stateValues.value).eqls([ - "*", - ["^", 3, "x"], - 2, - ]); - expect(stateVariables["/m15a"].stateValues.value).eqls([ - "^", - 3, - "x2", - ]); - }); - }); - - it("copy and overwrite split symbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

xyz

-

$m1{splitSymbols="false" name="m2"}

-

$m2{splitSymbols name="m3"}

- -

xyz

-

$m4{splitSymbols name="m5"}

-

$m5{splitSymbols="false" name="m6"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/m6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls("xyz"); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m4"].stateValues.value).eqls("xyz"); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/m6"].stateValues.value).eqls("xyz"); - }); - }); - - it("merge lists with other containers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

{a,b,c}

- -

{a,b,c,d,e,f}

-

(a,b,c,d,e,f)

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/set")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("{a,b,c}"); - }); - // cy.get(cesc('#\\/tuple')).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('(a,b,c)') - // }) - cy.get(cesc("#\\/combinedSet")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("{a,b,c,d,e,f}"); - }); - cy.get(cesc("#\\/combinedTuple")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(a,b,c,d,e,f)"); - }); - - cy.log("Test internal values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/set"].stateValues.value).eqls([ - "set", - "a", - "b", - "c", - ]); - // expect(stateVariables['/tuple'].stateValues.value).eqls(["tuple", "a", "b", "c"]); - expect(stateVariables["/combinedSet"].stateValues.value).eqls([ - "set", - "a", - "b", - "c", - "d", - "e", - "f", - ]); - expect(stateVariables["/combinedTuple"].stateValues.value).eqls([ - "tuple", - "a", - "b", - "c", - "d", - "e", - "f", - ]); - }); - }); - - it("components of math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

-

$m

-

$m

-

Ndimensions: $m $m2.numDimensions{assignNames="numDim2"} $m3.numDimensions{assignNames="numDim3"}

-

x: $m $m2.x{assignNames="x_2"} $m3.x{assignNames="x_3"}

-

y: $m $m2.y{assignNames="y_2"} $m3.y{assignNames="y_3"}

-

z: $m $m2.z{assignNames="z_2"} $m3.z{assignNames="z_3"}

-

x1: $m $m2.x1{assignNames="x1_2"} $m3.x1{assignNames="x1_3"}

-

x2: $m $m2.x2{assignNames="x2_2"} $m3.x2{assignNames="x2_3"}

-

x3: $m $m2.x3{assignNames="x3_2"} $m3.x3{assignNames="x3_3"}

-

x4: $m $m2.x4{assignNames="x4_2"} $m3.x4{assignNames="x4_3"}

-

x:

-

y:

-

z:

-

x1:

-

x2:

-

x3:

-

x4:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let indToComp = ["x", "y", "z"]; - - function check_values(xs, operator) { - cy.get(cesc(`#\\/numDim1`)).should( - "have.text", - xs.length.toString(), - ); - cy.get(cesc(`#\\/numDim2`)).should( - "have.text", - xs.length.toString(), - ); - - for (let [ind, x] of xs.entries()) { - let comp = indToComp[ind]; - if (comp) { - cy.get(cesc(`#\\/${comp}`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/βˆ’/g, "-")).equal( - x.toString(), - ); - }); - cy.get(cesc(`#\\/${comp}_2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/βˆ’/g, "-")).equal( - x.toString(), - ); - }); - cy.get(cesc(`#\\/${comp}_3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/βˆ’/g, "-")).equal( - x.toString(), - ); - }); - } - cy.get(cesc(`#\\/x${ind + 1}`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/βˆ’/g, "-")).equal( - x.toString(), - ); - }); - cy.get(cesc(`#\\/x${ind + 1}_2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/βˆ’/g, "-")).equal( - x.toString(), - ); - }); - cy.get(cesc(`#\\/x${ind + 1}_3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/βˆ’/g, "-")).equal( - x.toString(), - ); - }); - } - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/numDim1"].stateValues.value).eq( - xs.length, - ); - expect(stateVariables["/numDim2"].stateValues.value).eq( - xs.length, - ); - - let m3Operator = operator === "tuple" ? "vector" : operator; - - expect(stateVariables["/m"].stateValues.value).eqls([ - operator, - ...xs, - ]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - operator, - ...xs, - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - m3Operator, - ...xs, - ]); - - for (let [ind, x] of xs.entries()) { - let comp = indToComp[ind]; - if (comp) { - expect( - stateVariables[`/${comp}`].stateValues.value, - ).eqls(x); - expect( - stateVariables[`/${comp}_2`].stateValues.value, - ).eqls(x); - expect( - stateVariables[`/${comp}_3`].stateValues.value, - ).eqls(x); - } - expect( - stateVariables[`/x${ind + 1}`].stateValues.value, - ).eqls(x); - expect( - stateVariables[`/x${ind + 1}_2`].stateValues.value, - ).eqls(x); - expect( - stateVariables[`/x${ind + 1}_3`].stateValues.value, - ).eqls(x); - } - }); - } - - check_values(["a", "b", "c"], "tuple"); - - cy.log("change xyz 1"); - cy.get(cesc("#\\/mx") + " textarea").type("{end}{backspace}d{enter}", { - force: true, - }); - cy.get(cesc("#\\/my") + " textarea").type("{end}{backspace}e{enter}", { - force: true, - }); - cy.get(cesc("#\\/mz") + " textarea").type("{end}{backspace}f{enter}", { - force: true, - }); - cy.get(cesc("#\\/z")).should("contain.text", "f"); - check_values(["d", "e", "f"], "tuple"); - - cy.log("change xyz 2"); - cy.get(cesc("#\\/mx_2") + " textarea").type( - "{end}{backspace}g{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/my_2") + " textarea").type( - "{end}{backspace}h{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mz_2") + " textarea").type( - "{end}{backspace}i{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/z")).should("contain.text", "i"); - check_values(["g", "h", "i"], "tuple"); - - cy.log("change xyz 3"); - cy.get(cesc("#\\/mx_3") + " textarea").type( - "{end}{backspace}j{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/my_3") + " textarea").type( - "{end}{backspace}k{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mz_3") + " textarea").type( - "{end}{backspace}l{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/z")).should("contain.text", "l"); - check_values(["j", "k", "l"], "vector"); - - cy.log("change x1x2x3 1"); - cy.get(cesc("#\\/mx1") + " textarea").type("{end}{backspace}m{enter}", { - force: true, - }); - cy.get(cesc("#\\/mx2") + " textarea").type("{end}{backspace}n{enter}", { - force: true, - }); - cy.get(cesc("#\\/mx3") + " textarea").type("{end}{backspace}o{enter}", { - force: true, - }); - cy.get(cesc("#\\/z")).should("contain.text", "o"); - check_values(["m", "n", "o"], "vector"); - - cy.log("change x1x2x3 2"); - cy.get(cesc("#\\/mx1_2") + " textarea").type( - "{end}{backspace}p{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mx2_2") + " textarea").type( - "{end}{backspace}q{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mx3_2") + " textarea").type( - "{end}{backspace}r{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/z")).should("contain.text", "r"); - check_values(["p", "q", "r"], "vector"); - - cy.log("change x1x2x3 2"); - cy.get(cesc("#\\/mx1_3") + " textarea").type( - "{end}{backspace}s{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mx2_3") + " textarea").type( - "{end}{backspace}t{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mx3_3") + " textarea").type( - "{end}{backspace}u{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/z")).should("contain.text", "u"); - check_values(["s", "t", "u"], "vector"); - - cy.log("change to 4D list"); - cy.get(cesc("#\\/m") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}v,w,x,y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/x4")).should("contain.text", "y"); - - check_values(["v", "w", "x", "y"], "list"); - - cy.log("change x1x2x3x4 1"); - cy.get(cesc("#\\/mx1") + " textarea").type("{end}{backspace}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/mx2") + " textarea").type("{end}{backspace}a{enter}", { - force: true, - }); - cy.get(cesc("#\\/mx3") + " textarea").type("{end}{backspace}b{enter}", { - force: true, - }); - cy.get(cesc("#\\/mx4") + " textarea").type("{end}{backspace}c{enter}", { - force: true, - }); - cy.get(cesc("#\\/x4")).should("contain.text", "c"); - check_values(["z", "a", "b", "c"], "list"); - - cy.log("change x1x2x3x4 2"); - cy.get(cesc("#\\/mx1_2") + " textarea").type( - "{end}{backspace}d{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mx2_2") + " textarea").type( - "{end}{backspace}e{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mx3_2") + " textarea").type( - "{end}{backspace}f{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mx4_2") + " textarea").type( - "{end}{backspace}g{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/x4")).should("contain.text", "g"); - check_values(["d", "e", "f", "g"], "list"); - - cy.log("change to 3D alt vector"); - cy.get(cesc("#\\/m") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}\\langle a,b,c\\rangle {enter}", - { force: true }, - ); - cy.get(cesc("#\\/z")).should("contain.text", "c"); - - check_values(["a", "b", "c"], "altvector"); - - cy.log("change xyz 3"); - cy.get(cesc("#\\/mx_3") + " textarea").type( - "{end}{backspace}j{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/my_3") + " textarea").type( - "{end}{backspace}k{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mz_3") + " textarea").type( - "{end}{backspace}l{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/z")).should("contain.text", "l"); - check_values(["j", "k", "l"], "altvector"); - }); - - it("aslist inside math, group", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - a - b - c - - - - $grp - $grp{asList} - ($grp) - ($grp{asList}) - 2$grp - 2$grp{asList} - $grp, sin(x) - $grp{asList}, sin(x) - f($grp) - f($grp{asList}) - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/nolist") + " .mjx-mrow") - .eq(0) - .should("have.text", "abc"); - - cy.get(cesc2("#/list") + " .mjx-mrow") - .eq(0) - .should("have.text", "a,b,c"); - - cy.get(cesc2("#/nolist2") + " .mjx-mrow") - .eq(0) - .should("have.text", "abc"); - - cy.get(cesc2("#/tuple") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a,b,c)"); - - cy.get(cesc2("#/doubleNoList") + " .mjx-mrow") - .eq(0) - .should("have.text", "2abc"); - - cy.get(cesc2("#/doubleTuple") + " .mjx-mrow") - .eq(0) - .should("have.text", "2(a,b,c)"); - - cy.get(cesc2("#/appendNoList") + " .mjx-mrow") - .eq(0) - .should("have.text", "abc,sin(x)"); - - cy.get(cesc2("#/appendToList") + " .mjx-mrow") - .eq(0) - .should("have.text", "a,b,c,sin(x)"); - - cy.get(cesc2("#/functionNoList") + " .mjx-mrow") - .eq(0) - .should("have.text", "f(abc)"); - - cy.get(cesc2("#/functionOfList") + " .mjx-mrow") - .eq(0) - .should("have.text", "f(a,b,c)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/nolist"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/nolist"].stateValues.text).eq("a b c"); - - expect(stateVariables["/list"].stateValues.value).eqls([ - "list", - "a", - "b", - "c", - ]); - expect(stateVariables["/list"].stateValues.text).eq("a, b, c"); - - expect(stateVariables["/nolist2"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/nolist2"].stateValues.text).eq("a b c"); - - expect(stateVariables["/tuple"].stateValues.value).eqls([ - "tuple", - "a", - "b", - "c", - ]); - expect(stateVariables["/tuple"].stateValues.text).eq("( a, b, c )"); - - expect(stateVariables["/doubleNoList"].stateValues.value).eqls([ - "*", - 2, - "a", - "b", - "c", - ]); - expect(stateVariables["/doubleNoList"].stateValues.text).eq( - "2 a b c", - ); - - expect(stateVariables["/doubleTuple"].stateValues.value).eqls([ - "*", - 2, - ["tuple", "a", "b", "c"], - ]); - expect(stateVariables["/doubleTuple"].stateValues.text).eq( - "2 ( a, b, c )", - ); - - expect(stateVariables["/appendNoList"].stateValues.value).eqls([ - "list", - ["*", "a", "b", "c"], - ["apply", "sin", "x"], - ]); - expect(stateVariables["/appendNoList"].stateValues.text).eq( - "a b c, sin(x)", - ); - - expect(stateVariables["/appendToList"].stateValues.value).eqls([ - "list", - "a", - "b", - "c", - ["apply", "sin", "x"], - ]); - expect(stateVariables["/appendToList"].stateValues.text).eq( - "a, b, c, sin(x)", - ); - - expect(stateVariables["/functionNoList"].stateValues.value).eqls([ - "apply", - "f", - ["*", "a", "b", "c"], - ]); - expect(stateVariables["/functionNoList"].stateValues.text).eq( - "f(a b c)", - ); - - expect(stateVariables["/functionOfList"].stateValues.value).eqls([ - "apply", - "f", - ["tuple", "a", "b", "c"], - ]); - expect(stateVariables["/functionOfList"].stateValues.text).eq( - "f( a, b, c )", - ); - }); - }); - - it("aslist inside math, sequence", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - $seq - $seq{asList="false"} - ($seq) - ($seq{asList="false"}) - 2$seq - 2$seq{asList="false"} - $seq, sin(x) - $seq{asList="false"}, sin(x) - sum($seq) - sum($seq{asList="false"}) - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/list") + " .mjx-mrow") - .eq(0) - .should("have.text", "1,2,3,4"); - - cy.get(cesc2("#/nolist") + " .mjx-mrow") - .eq(0) - .should("have.text", "24"); - - cy.get(cesc2("#/tuple") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2,3,4)"); - - cy.get(cesc2("#/nolist2") + " .mjx-mrow") - .eq(0) - .should("have.text", "24"); - - cy.get(cesc2("#/doubleTuple") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,4,6,8)"); - - cy.get(cesc2("#/doubleNoList") + " .mjx-mrow") - .eq(0) - .should("have.text", "48"); - - cy.get(cesc2("#/appendToList") + " .mjx-mrow") - .eq(0) - .should("have.text", "1,2,3,4,sin(x)"); - - cy.get(cesc2("#/appendNoList") + " .mjx-mrow") - .eq(0) - .should("have.text", "24,sin(x)"); - - cy.get(cesc2("#/functionOfList") + " .mjx-mrow") - .eq(0) - .should("have.text", "10"); - - cy.get(cesc2("#/functionNoList") + " .mjx-mrow") - .eq(0) - .should("have.text", "24"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/list"].stateValues.value).eqls([ - "list", - 1, - 2, - 3, - 4, - ]); - - expect(stateVariables["/nolist"].stateValues.value).eq(24); - - expect(stateVariables["/tuple"].stateValues.value).eqls([ - "tuple", - 1, - 2, - 3, - 4, - ]); - - expect(stateVariables["/nolist2"].stateValues.value).eq(24); - - expect(stateVariables["/doubleTuple"].stateValues.value).eqls([ - "tuple", - 2, - 4, - 6, - 8, - ]); - - expect(stateVariables["/doubleNoList"].stateValues.value).eq(48); - - expect(stateVariables["/appendToList"].stateValues.value).eqls([ - "list", - 1, - 2, - 3, - 4, - ["apply", "sin", "x"], - ]); - - expect(stateVariables["/appendNoList"].stateValues.value).eqls([ - "list", - 24, - ["apply", "sin", "x"], - ]); - - expect(stateVariables["/functionOfList"].stateValues.value).eq(10); - - expect(stateVariables["/functionNoList"].stateValues.value).eq(24); - }); - }); - - it("aslist inside math, map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - - $map - $map{asList="false"} - ($map) - ($map{asList="false"}) - 2$map - 2$map{asList="false"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/list") + " .mjx-mrow") - .eq(0) - .should("have.text", "x,4x,9x"); - - cy.get(cesc2("#/nolist") + " .mjx-mrow") - .eq(0) - .should("have.text", "36x3"); - - cy.get(cesc2("#/tuple") + " .mjx-mrow") - .eq(0) - .should("have.text", "(x,4x,9x)"); - - cy.get(cesc2("#/nolist2") + " .mjx-mrow") - .eq(0) - .should("have.text", "36x3"); - - cy.get(cesc2("#/doubleTuple") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2x,8x,18x)"); - - cy.get(cesc2("#/doubleNoList") + " .mjx-mrow") - .eq(0) - .should("have.text", "72x3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/list"].stateValues.value).eqls([ - "list", - "x", - ["*", 4, "x"], - ["*", 9, "x"], - ]); - - expect(stateVariables["/nolist"].stateValues.value).eqls([ - "*", - 36, - ["^", "x", 3], - ]); - - expect(stateVariables["/tuple"].stateValues.value).eqls([ - "tuple", - "x", - ["*", 4, "x"], - ["*", 9, "x"], - ]); - - expect(stateVariables["/nolist2"].stateValues.value).eqls([ - "*", - 36, - ["^", "x", 3], - ]); - - expect(stateVariables["/doubleTuple"].stateValues.value).eqls([ - "tuple", - ["*", 2, "x"], - ["*", 8, "x"], - ["*", 18, "x"], - ]); - - expect(stateVariables["/doubleNoList"].stateValues.value).eqls([ - "*", - 72, - ["^", "x", 3], - ]); - }); - }); - - it("math inherits unordered of children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- 2,3 - 4(2,3) - 4(2,3) - 2,3 - 4(2,3) - 2,3 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/unordered1"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/unordered2"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/unordered3"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/ordered1"].stateValues.unordered).eq(false); - expect(stateVariables["/ordered2"].stateValues.unordered).eq(false); - expect(stateVariables["/ordered3"].stateValues.unordered).eq(false); - }); - }); - - it("copy math and overwrite unordered", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- 2,3 - $ordered1{unordered name="unordered1"} - $unordered1{unordered="false" name="ordered2"} - - 2,3 - $unordered2{unordered="false" name="ordered3"} - $ordered3{unordered name="unordered3"} - - 2,3 - $unordered4{unordered="false" name="ordered4"} - $ordered4{unordered name="unordered5"} - - 2,3 - $ordered5{unordered name="unordered6"} - $unordered6{unordered="false" name="ordered6"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/unordered1"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/unordered2"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/unordered3"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/unordered4"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/unordered5"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/unordered6"].stateValues.unordered).eq( - true, - ); - expect(stateVariables["/ordered1"].stateValues.unordered).eq(false); - expect(stateVariables["/ordered2"].stateValues.unordered).eq(false); - expect(stateVariables["/ordered3"].stateValues.unordered).eq(false); - expect(stateVariables["/ordered4"].stateValues.unordered).eq(false); - expect(stateVariables["/ordered5"].stateValues.unordered).eq(false); - expect(stateVariables["/ordered6"].stateValues.unordered).eq(false); - }); - }); - - it("copy math and overwrite unordered, change dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- - - - -

- 2,3 - $m1{unordered="$(../b2)" name="m2"} - $m2{unordered="$(../b3)" name="m3"} -

- - $p1{name="p2"} -

- $b1.value{assignNames="b1a"} - $b2.value{assignNames="b2a"} - $b3.value{assignNames="b3a"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1/m1"].stateValues.unordered).eq(true); - expect(stateVariables["/p1/m2"].stateValues.unordered).eq(false); - expect(stateVariables["/p1/m3"].stateValues.unordered).eq(true); - expect(stateVariables["/p2/m1"].stateValues.unordered).eq(true); - expect(stateVariables["/p2/m2"].stateValues.unordered).eq(false); - expect(stateVariables["/p2/m3"].stateValues.unordered).eq(true); - }); - - cy.get(cesc("#\\/b1")).click(); - cy.get(cesc("#\\/b1a")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1/m1"].stateValues.unordered).eq(false); - expect(stateVariables["/p1/m2"].stateValues.unordered).eq(false); - expect(stateVariables["/p1/m3"].stateValues.unordered).eq(true); - expect(stateVariables["/p2/m1"].stateValues.unordered).eq(false); - expect(stateVariables["/p2/m2"].stateValues.unordered).eq(false); - expect(stateVariables["/p2/m3"].stateValues.unordered).eq(true); - }); - - cy.get(cesc("#\\/b2")).click(); - cy.get(cesc("#\\/b2a")).should("have.text", "true"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1/m1"].stateValues.unordered).eq(false); - expect(stateVariables["/p1/m2"].stateValues.unordered).eq(true); - expect(stateVariables["/p1/m3"].stateValues.unordered).eq(true); - expect(stateVariables["/p2/m1"].stateValues.unordered).eq(false); - expect(stateVariables["/p2/m2"].stateValues.unordered).eq(true); - expect(stateVariables["/p2/m3"].stateValues.unordered).eq(true); - }); - - cy.get(cesc("#\\/b3")).click(); - cy.get(cesc("#\\/b3a")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1/m1"].stateValues.unordered).eq(false); - expect(stateVariables["/p1/m2"].stateValues.unordered).eq(true); - expect(stateVariables["/p1/m3"].stateValues.unordered).eq(false); - expect(stateVariables["/p2/m1"].stateValues.unordered).eq(false); - expect(stateVariables["/p2/m2"].stateValues.unordered).eq(true); - expect(stateVariables["/p2/m3"].stateValues.unordered).eq(false); - }); - }); - - it("shrink vector dimensions in inverse direction", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- (x,y,z) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x,y,z)"); - }); - - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}{leftArrow}{backspace}{backspace}", { force: true }) - .blur(); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "(x,y)"); - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x,y)"); - }); - }); - - it("change one vector component in inverse direction does not affect other", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- 1 - - - $P{name="Q" x="2$n-1"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs.map((x) => x)).eqls([ - 3, 1, - ]); - expect(stateVariables["/Q"].stateValues.xs.map((x) => x)).eqls([ - 1, 1, - ]); - }); - - cy.log("move dependent point"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - await win.callAction1({ - actionName: "movePoint", - componentName: "/Q", - args: { x: -2, y: 3 }, - }); - }); - - cy.get(cesc("#\\/n")).should("have.text", "-0.5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs.map((x) => x)).eqls([ - 0, 3, - ]); - expect(stateVariables["/Q"].stateValues.xs.map((x) => x)).eqls([ - -2, 3, - ]); - }); - }); - - it("change one vector component in inverse direction does not affect other, original in math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- 1 - (2$n+1,1) - - - $P{name="Q" x="2$n-1"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/coords")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs.map((x) => x)).eqls([ - 3, 1, - ]); - expect(stateVariables["/Q"].stateValues.xs.map((x) => x)).eqls([ - 1, 1, - ]); - }); - - cy.log("move dependent point"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - await win.callAction1({ - actionName: "movePoint", - componentName: "/Q", - args: { x: -2, y: 3 }, - }); - }); - - cy.get(cesc("#\\/n")).should("have.text", "-0.5"); - cy.get(cesc("#\\/coords")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,3)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs.map((x) => x)).eqls([ - 0, 3, - ]); - expect(stateVariables["/Q"].stateValues.xs.map((x) => x)).eqls([ - -2, 3, - ]); - }); - }); - - it("change one vector component in inverse direction does not affect other, through mathinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- 1 - (2$n+1,1) - - - - $P{name="Q" x="2$n-1"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/coords1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs.map((x) => x)).eqls([ - 3, 1, - ]); - expect(stateVariables["/Q"].stateValues.xs.map((x) => x)).eqls([ - 1, 1, - ]); - }); - - cy.log("move dependent point"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - await win.callAction1({ - actionName: "movePoint", - componentName: "/Q", - args: { x: -2, y: 3 }, - }); - }); - - cy.get(cesc("#\\/n")).should("have.text", "-0.5"); - cy.get(cesc("#\\/coords1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,3)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs.map((x) => x)).eqls([ - 0, 3, - ]); - expect(stateVariables["/Q"].stateValues.xs.map((x) => x)).eqls([ - -2, 3, - ]); - }); - - cy.log("enter value in mathinput"); - cy.get(cesc("#\\/coords2") + " textarea").type( - "{end}{leftArrow}{backspace}{backspace}{backspace}6,9{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/n")).should("have.text", "2.5"); - cy.get(cesc("#\\/coords1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,9)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs.map((x) => x)).eqls([ - 6, 9, - ]); - expect(stateVariables["/Q"].stateValues.xs.map((x) => x)).eqls([ - 4, 9, - ]); - }); - }); - - it("copy value prop copies attributes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

8.5203845251 - - - - -

- -

8.5203845251 - - - - -

- -

0.000000000000000015382487 - - - - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52"); - cy.get(cesc("#\\/m1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52"); - cy.get(cesc("#\\/m1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52"); - cy.get(cesc("#\\/m1d") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.520385"); - cy.get(cesc("#\\/m2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m2d") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.520385"); - - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.54β‹…10βˆ’17"); - cy.get(cesc("#\\/m3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.54β‹…10βˆ’17"); - cy.get(cesc("#\\/m3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/m3c") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.54β‹…10βˆ’17"); - cy.get(cesc("#\\/m3d") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - }); - - // TODO: fix so doesn't break when copy the math, not just copy its value - it("set vector component to undefined", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- (x,y) - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "(x,y)"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(x,y)"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", "x"); - - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}{backspace}{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/m")).should("contain.text", "(οΌΏ,y)"); - - cy.get(cesc("#\\/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "(οΌΏ,y)"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(οΌΏ,y)"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", ""); - - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}q{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/m")).should("contain.text", "(q,y)"); - - cy.get(cesc("#\\/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "(q,y)"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(q,y)"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", "q"); - }); - - it("negative zero", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

-0

-

4 - 0

-

0 - 0

-

-0 - 0

-

0 + -0

-

0 - - 0

-

-6/-0

- -

4 + -0

-

4 - -0

-

-0 + -0

-

-0 - -0

-

-6/-0

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’0"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "4βˆ’0"); - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "0βˆ’0"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’0βˆ’0"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "0βˆ’0"); - cy.get(cesc("#\\/m6") + " .mjx-mrow") - .eq(0) - .should("have.text", "0βˆ’βˆ’0"); - cy.get(cesc("#\\/m7") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’6βˆ’0"); - - cy.get(cesc("#\\/m8") + " .mjx-mrow") - .eq(0) - .should("have.text", "4βˆ’0"); - cy.get(cesc("#\\/m9") + " .mjx-mrow") - .eq(0) - .should("have.text", "4βˆ’βˆ’0"); - cy.get(cesc("#\\/m10") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’0βˆ’0"); - cy.get(cesc("#\\/m11") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’0βˆ’βˆ’0"); - cy.get(cesc("#\\/m12") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’6βˆ’0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/m1"].stateValues.value).eqls(["-", 0]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "+", - 4, - ["-", 0], - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "+", - 0, - ["-", 0], - ]); - expect(stateVariables["/m4"].stateValues.value).eqls([ - "+", - ["-", 0], - ["-", 0], - ]); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "+", - 0, - ["-", 0], - ]); - expect(stateVariables["/m6"].stateValues.value).eqls([ - "+", - 0, - ["-", ["-", 0]], - ]); - expect(stateVariables["/m7"].stateValues.value).eqls([ - "-", - ["/", 6, ["-", 0]], - ]); - - expect(stateVariables["/m8"].stateValues.value).eqls([ - "+", - 4, - ["-", 0], - ]); - expect(stateVariables["/m9"].stateValues.value).eqls([ - "+", - 4, - ["-", ["-", 0]], - ]); - expect(stateVariables["/m10"].stateValues.value).eqls([ - "+", - ["-", 0], - ["-", 0], - ]); - expect(stateVariables["/m11"].stateValues.value).eqls([ - "+", - ["-", 0], - ["-", ["-", 0]], - ]); - expect(stateVariables["/m12"].stateValues.value).eqls([ - "/", - -6, - ["-", 0], - ]); - }); - }); - - it("parse <", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

x < y

-

x <= y

-

x < - y

-

x <= - y

-

x < y

-

x <= y

- -

x < y

-

x < - y

-

x \\lt y

-

x < y

-

x \\le y

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/m1"].stateValues.value).eqls([ - "<", - "x", - "y", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "le", - "x", - "y", - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "<", - "x", - "y", - ]); - expect(stateVariables["/m4"].stateValues.value).eqls([ - "le", - "x", - "y", - ]); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "<", - "x", - "y", - ]); - expect(stateVariables["/m6"].stateValues.value).eqls([ - "le", - "x", - "y", - ]); - expect(stateVariables["/m7"].stateValues.value).eqls([ - "<", - "x", - "y", - ]); - expect(stateVariables["/m8"].stateValues.value).eqls([ - "<", - "x", - "y", - ]); - expect(stateVariables["/m9"].stateValues.value).eqls([ - "<", - "x", - "y", - ]); - expect(stateVariables["/m10"].stateValues.value).eqls([ - "<", - "x", - "y", - ]); - expect(stateVariables["/m11"].stateValues.value).eqls([ - "le", - "x", - "y", - ]); - }); - }); - - it("display rounding preserved when only one math child", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

8.5203845251 - 8.5203845251 - 8.5203845251x+526195.5352 - 8.5203845251x+526195.5352 - 8.5203845251x - 8.5203845251x - 8.5203845251 - 8.5203845251+582342.423835237238 -

- -

- - - - - - - -

- -

8.5203845251 - 8.5203845251 - 8.5203845251x+526195.5352 - 8.5203845251x+526195.5352 - 8.5203845251x - 8.5203845251x - 8.5203845251 - 8.5203845251+582342.423835237238 -

- -

- - - - - - - -

- -

0.000000000000000015382487 - 0.000000000000000015382487 - 0.000000000000000015382487x+526195.5352 - 0.000000000000000015382487x+526195.5352 - 0.000000000000000015382487x - 0.000000000000000015382487x - 0.000000000000000015382487 -

- -

- - - - - - -

- -

8 - 8 - 8x+526195.5352 - 8x+526195.5352 - 8x - 8x - 8 -

- -

- - - - - - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x+526195.54"); - cy.get(cesc("#\\/m1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x+526195.54"); - cy.get(cesc("#\\/m1d") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x"); - cy.get(cesc("#\\/m1e") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x"); - cy.get(cesc("#\\/m1f") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.520385"); - cy.get(cesc("#\\/m1g") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204+582342.4238"); - - cy.get(cesc("#\\/m1_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m1a_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m1b_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x+526195.54"); - cy.get(cesc("#\\/m1c_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x+526195.54"); - cy.get(cesc("#\\/m1d_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x"); - cy.get(cesc("#\\/m1e_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x"); - cy.get(cesc("#\\/m1f_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.520385"); - cy.get(cesc("#\\/m1g_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204+582342.4238"); - - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x+526195.54"); - cy.get(cesc("#\\/m2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x+526195.54"); - cy.get(cesc("#\\/m2d") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x"); - cy.get(cesc("#\\/m2e") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x"); - cy.get(cesc("#\\/m2f") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.520385"); - cy.get(cesc("#\\/m2g") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5203845+582342.42"); - - cy.get(cesc("#\\/m2_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m2a_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5204"); - cy.get(cesc("#\\/m2b_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x+526195.54"); - cy.get(cesc("#\\/m2c_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x+526195.54"); - cy.get(cesc("#\\/m2d_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x"); - cy.get(cesc("#\\/m2e_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.52x"); - cy.get(cesc("#\\/m2f_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.520385"); - cy.get(cesc("#\\/m2g_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.5203845+582342.42"); - - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.54β‹…10βˆ’17"); - cy.get(cesc("#\\/m3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.54β‹…10βˆ’17"); - cy.get(cesc("#\\/m3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "0x+526195.54"); - cy.get(cesc("#\\/m3c") + " .mjx-mrow") - .eq(0) - .should("have.text", "0x+526195.54"); - cy.get(cesc("#\\/m3d") + " .mjx-mrow") - .eq(0) - .should("have.text", "0x"); - cy.get(cesc("#\\/m3e") + " .mjx-mrow") - .eq(0) - .should("have.text", "0x"); - cy.get(cesc("#\\/m3f") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - - cy.get(cesc("#\\/m3_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.54β‹…10βˆ’17"); - cy.get(cesc("#\\/m3a_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1.54β‹…10βˆ’17"); - cy.get(cesc("#\\/m3b_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "0x+526195.54"); - cy.get(cesc("#\\/m3c_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "0x+526195.54"); - cy.get(cesc("#\\/m3d_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "0x"); - cy.get(cesc("#\\/m3e_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "0x"); - cy.get(cesc("#\\/m3f_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.0000"); - cy.get(cesc("#\\/m4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.0000"); - cy.get(cesc("#\\/m4b") + " .mjx-mrow") - .eq(0) - .should("have.text", "8x+526195.54"); - cy.get(cesc("#\\/m4c") + " .mjx-mrow") - .eq(0) - .should("have.text", "8x+526195.54"); - cy.get(cesc("#\\/m4d") + " .mjx-mrow") - .eq(0) - .should("have.text", "8x"); - cy.get(cesc("#\\/m4e") + " .mjx-mrow") - .eq(0) - .should("have.text", "8x"); - cy.get(cesc("#\\/m4f") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - - cy.get(cesc("#\\/m4_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.0000"); - cy.get(cesc("#\\/m4a_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.0000"); - cy.get(cesc("#\\/m4b_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8x+526195.54"); - cy.get(cesc("#\\/m4c_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8x+526195.54"); - cy.get(cesc("#\\/m4d_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8x"); - cy.get(cesc("#\\/m4e_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8x"); - cy.get(cesc("#\\/m4f_v") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - }); - - it("negative integer to power of integer", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- (-3)^2 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’3)2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.latex).eq( - "\\left(-3\\right)^{2}", - ); - }); - }); - - it("can get negative infinity from reciprocal when simplify", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- 1/((0)(-1)) - 1/((-1)(0)) - 1/(-0) - 1/(-1(0)) - -1/0 - -1/((-1)(-0)) - - 1/((-0)(-1)) - 1/((-1)(-0)) - -1/(-0) - 1/(-1(-0)) - 1/0 - -1/((0)(-1)) - -1/((-1)(0)) - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/ninf1") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’βˆž"); - cy.get(cesc("#\\/ninf2") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’βˆž"); - cy.get(cesc("#\\/ninf3") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’βˆž"); - cy.get(cesc("#\\/ninf4") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’βˆž"); - cy.get(cesc("#\\/ninf5") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’βˆž"); - cy.get(cesc("#\\/ninf6") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’βˆž"); - - cy.get(cesc("#\\/pinf1") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - cy.get(cesc("#\\/pinf2") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - cy.get(cesc("#\\/pinf3") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - cy.get(cesc("#\\/pinf4") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - cy.get(cesc("#\\/pinf5") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - cy.get(cesc("#\\/pinf6") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - cy.get(cesc("#\\/pinf7") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ninf1"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf2"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf3"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf4"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf5"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf6"].stateValues.value).eq(-Infinity); - - expect(stateVariables["/pinf1"].stateValues.value).eq(Infinity); - expect(stateVariables["/pinf2"].stateValues.value).eq(Infinity); - expect(stateVariables["/pinf3"].stateValues.value).eq(Infinity); - expect(stateVariables["/pinf4"].stateValues.value).eq(Infinity); - expect(stateVariables["/pinf5"].stateValues.value).eq(Infinity); - expect(stateVariables["/pinf6"].stateValues.value).eq(Infinity); - expect(stateVariables["/pinf7"].stateValues.value).eq(Infinity); - }); - }); - - it("display blanks", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

Display blanks:

-

x^() + /2

-

+++

-

2+

-

2+2+

-

'-_^

-

)

-

(,]

-

2+()

-

2+()+5

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+2"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "+++"); - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2+"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "2+2+"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "β€²βˆ’"); - cy.get(cesc("#\\/m6") + " .mjx-mrow") - .eq(0) - .should("have.text", ""); - cy.get(cesc("#\\/m7") + " .mjx-mrow") - .eq(0) - .should("have.text", "(,]"); - cy.get(cesc("#\\/m8") + " .mjx-mrow") - .eq(0) - .should("have.text", "2+"); - cy.get(cesc("#\\/m9") + " .mjx-mrow") - .eq(0) - .should("have.text", "2++5"); - - cy.get(cesc("#\\/displayBlanks")).click(); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x\uff3f+\uff3f2"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "+++"); - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2+"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "2+2+\uff3f"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3fβ€²βˆ’\uff3f\uff3f\uff3f"); - cy.get(cesc("#\\/m6") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m7") + " .mjx-mrow") - .eq(0) - .should("have.text", "(\uff3f,\uff3f]"); - cy.get(cesc("#\\/m8") + " .mjx-mrow") - .eq(0) - .should("have.text", "2+\uff3f"); - cy.get(cesc("#\\/m9") + " .mjx-mrow") - .eq(0) - .should("have.text", "2+\uff3f+5"); - }); - - it("changes are reloaded correctly.", () => { - let doenetML = ` -

a

-

w

-

x + y

-

z

-

a+$m4

-

-

-

-

-

- `; - - 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, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "w"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+y"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+z"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls("w"); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/m3"].stateValues.value).eqls("y"); - expect(stateVariables["/m4"].stateValues.value).eqls("z"); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "+", - "a", - "z", - ]); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi2") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi4") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m4") + " .mjx-mrow").should("contain.text", "3"); - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+2"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls(1); - expect(stateVariables["/m2"].stateValues.value).eqls(["+", "x", 2]); - expect(stateVariables["/m3"].stateValues.value).eqls(2); - expect(stateVariables["/m4"].stateValues.value).eqls(3); - expect(stateVariables["/m5"].stateValues.value).eqls(["+", "a", 3]); - }); - - cy.wait(1500); // wait for debounce - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - return stateVariables["/m1"]; - }), - ); - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+2"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls(1); - expect(stateVariables["/m2"].stateValues.value).eqls(["+", "x", 2]); - expect(stateVariables["/m3"].stateValues.value).eqls(2); - expect(stateVariables["/m4"].stateValues.value).eqls(3); - expect(stateVariables["/m5"].stateValues.value).eqls(["+", "a", 3]); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{end}{backspace}4+5{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mi3") + " textarea").type( - "{end}{backspace}6+7{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mi5") + " textarea").type( - "{end}{backspace}8+9{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/m5") + " .mjx-mrow").should("contain.text", "17"); - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "4+5"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+6+7"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "17"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+17"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls(["+", 4, 5]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "+", - "x", - 6, - 7, - ]); - expect(stateVariables["/m3"].stateValues.value).eqls(["+", 6, 7]); - expect(stateVariables["/m4"].stateValues.value).eqls(17); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "+", - "a", - 17, - ]); - }); - - cy.wait(1500); // wait for debounce - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - return stateVariables["/m1"]; - }), - ); - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "4+5"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+6+7"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "17"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+17"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eqls(["+", 4, 5]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "+", - "x", - 6, - 7, - ]); - expect(stateVariables["/m3"].stateValues.value).eqls(["+", 6, 7]); - expect(stateVariables["/m4"].stateValues.value).eqls(17); - expect(stateVariables["/m5"].stateValues.value).eqls([ - "+", - "a", - 17, - ]); - }); - }); - - it("add and subtract vectors, multiply by scalar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

Tuple2: (a,b)

-

Vector2: (c,d)

-

Alt vector2: ⟨p,q⟩

-

Interval: (e,f)

-

Tuple3: (g,h,i)

-

Vector3: (j,k,l)

-

Alt vector3: ⟨r,s,t⟩

-

$tuple2+$tuple2

-

$tuple2+$tuple2

-

$vector2+$vector2

-

$vector2+$vector2

-

$altvector2+$altvector2

-

$altvector2+$altvector2

-

$interval+$interval

-

$interval+$interval

-

$tuple2+$vector2

-

$tuple2+$vector2

-

$vector2+$tuple2

-

$vector2+$tuple2

-

$tuple2+$altvector2

-

$tuple2+$altvector2

-

$altvector2+$tuple2

-

$altvector2+$tuple2

-

$vector2+$altvector2

-

$vector2+$altvector2

-

$altvector2+$vector2

-

$altvector2+$vector2

-

$tuple2-$vector2

-

$tuple2-$vector2

-

$vector2-$tuple2

-

$vector2-$tuple2

-

$tuple2-$altvector2

-

$tuple2-$altvector2

-

$altvector2-$tuple2

-

$altvector2-$tuple2

-

$vector2-$altvector2

-

$vector2-$altvector2

-

$altvector2-$vector2

-

$altvector2-$vector2

-

$tuple2+$interval

-

$tuple2+$interval

-

$vector2+$interval

-

$vector2+$interval

-

$altvector2+$interval

-

$altvector2+$interval

-

m$tuple2

-

m$tuple2

-

m$tuple2

-

$tuple2 m

-

$tuple2 m

-

$tuple2 m

-

m$vector2

-

m$vector2

-

m$vector2

-

$vector2 m

-

$vector2 m

-

$vector2 m

-

m$altvector2

-

m$altvector2

-

m$altvector2

-

$altvector2 m

-

$altvector2 m

-

$altvector2 m

-

m$interval

-

m$interval

-

m$interval

-

$interval m

-

$interval m

-

$interval m

-

m$tuple2+$vector2*n

-

m$tuple2+$vector2*n

-

m$tuple2+$vector2*n

-

m$tuple2+$altvector2*n

-

m$tuple2+$altvector2*n

-

m$tuple2+$altvector2*n

-

m$vector2+$altvector2*n

-

m$vector2+$altvector2*n

-

m$vector2+$altvector2*n

- -

$tuple3+$tuple3

-

$tuple3+$tuple3

-

$vector3+$vector3

-

$vector3+$vector3

-

$altvector3+$altvector3

-

$altvector3+$altvector3

-

$tuple3+$vector3

-

$tuple3+$vector3

-

$vector3+$tuple3

-

$vector3+$tuple3

-

$tuple3+$altvector3

-

$tuple3+$altvector3

-

$altvector3+$tuple3

-

$altvector3+$tuple3

-

$vector3+$altvector3

-

$vector3+$altvector3

-

$altvector3+$vector3

-

$altvector3+$vector3

-

$tuple3-$vector3

-

$tuple3-$vector3

-

$vector3-$tuple3

-

$vector3-$tuple3

-

$tuple3-$altvector3

-

$tuple3-$altvector3

-

$altvector3-$tuple3

-

$altvector3-$tuple3

-

$vector3-$altvector3

-

$vector3-$altvector3

-

$altvector3-$vector3

-

$altvector3-$vector3

-

m$tuple3

-

m$tuple3

-

m$tuple3

-

$tuple3 m

-

$tuple3 m

-

$tuple3 m

-

m$vector3

-

m$vector3

-

m$vector3

-

$vector3 m

-

$vector3 m

-

$vector3 m

-

m$altvector3

-

m$altvector3

-

m$altvector3

-

$altvector3 m

-

$altvector3 m

-

$altvector3 m

-

m$tuple3+$vector3*n

-

m$tuple3+$vector3*n

-

m$tuple3+$vector3*n

-

m$tuple3+$altvector3*n

-

m$tuple3+$altvector3*n

-

m$tuple3+$altvector3*n

-

m$vector3+$altvector3*n

-

m$vector3+$altvector3*n

-

m$vector3+$altvector3*n

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/t2t2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a,b)+(a,b)"); - cy.get(cesc("#\\/t2t2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2a,2b)"); - cy.get(cesc("#\\/v2v2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c,d)+(c,d)"); - cy.get(cesc("#\\/v2v2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2c,2d)"); - cy.get(cesc("#\\/a2a2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,q⟩+⟨p,q⟩"); - cy.get(cesc("#\\/a2a2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨2p,2q⟩"); - cy.get(cesc("#\\/iisum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(e,f)+(e,f)"); - cy.get(cesc("#\\/iisumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "2(e,f)"); - cy.get(cesc("#\\/t2v2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a,b)+(c,d)"); - cy.get(cesc("#\\/t2v2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a+c,b+d)"); - cy.get(cesc("#\\/v2t2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c,d)+(a,b)"); - cy.get(cesc("#\\/v2t2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a+c,b+d)"); - cy.get(cesc("#\\/t2a2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a,b)+⟨p,q⟩"); - cy.get(cesc("#\\/t2a2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a+p,b+q)"); - cy.get(cesc("#\\/a2t2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,q⟩+(a,b)"); - cy.get(cesc("#\\/a2t2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a+p,b+q)"); - cy.get(cesc("#\\/v2a2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c,d)+⟨p,q⟩"); - cy.get(cesc("#\\/v2a2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c+p,d+q)"); - cy.get(cesc("#\\/a2v2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,q⟩+(c,d)"); - cy.get(cesc("#\\/a2v2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c+p,d+q)"); - cy.get(cesc("#\\/t2v2diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a,b)βˆ’(c,d)"); - cy.get(cesc("#\\/t2v2diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(aβˆ’c,bβˆ’d)"); - cy.get(cesc("#\\/v2t2diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c,d)βˆ’(a,b)"); - cy.get(cesc("#\\/v2t2diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’a+c,βˆ’b+d)"); - cy.get(cesc("#\\/t2a2diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a,b)βˆ’βŸ¨p,q⟩"); - cy.get(cesc("#\\/t2a2diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(aβˆ’p,bβˆ’q)"); - cy.get(cesc("#\\/a2t2diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,qβŸ©βˆ’(a,b)"); - cy.get(cesc("#\\/a2t2diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’a+p,βˆ’b+q)"); - cy.get(cesc("#\\/v2a2diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c,d)βˆ’βŸ¨p,q⟩"); - cy.get(cesc("#\\/v2a2diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(cβˆ’p,dβˆ’q)"); - cy.get(cesc("#\\/a2v2diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,qβŸ©βˆ’(c,d)"); - cy.get(cesc("#\\/a2v2diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’c+p,βˆ’d+q)"); - cy.get(cesc("#\\/t2isum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a,b)+(e,f)"); - cy.get(cesc("#\\/t2isumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(e,f)+(a,b)"); - cy.get(cesc("#\\/v2isum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c,d)+(e,f)"); - cy.get(cesc("#\\/v2isumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(e,f)+(c,d)"); - cy.get(cesc("#\\/a2isum") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,q⟩+(e,f)"); - cy.get(cesc("#\\/a2isumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,q⟩+(e,f)"); - cy.get(cesc("#\\/st2mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(a,b)"); - cy.get(cesc("#\\/st2mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(am,bm)"); - cy.get(cesc("#\\/st2mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(am,bm)"); - cy.get(cesc("#\\/t2smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "(a,b)m"); - cy.get(cesc("#\\/t2smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(am,bm)"); - cy.get(cesc("#\\/t2smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(am,bm)"); - cy.get(cesc("#\\/sv2mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(c,d)"); - cy.get(cesc("#\\/sv2mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(cm,dm)"); - cy.get(cesc("#\\/sv2mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(cm,dm)"); - cy.get(cesc("#\\/v2smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "(c,d)m"); - cy.get(cesc("#\\/v2smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(cm,dm)"); - cy.get(cesc("#\\/v2smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(cm,dm)"); - cy.get(cesc("#\\/sa2mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m⟨p,q⟩"); - cy.get(cesc("#\\/sa2mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨mp,mq⟩"); - cy.get(cesc("#\\/sa2mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨mp,mq⟩"); - cy.get(cesc("#\\/a2smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,q⟩m"); - cy.get(cesc("#\\/a2smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨mp,mq⟩"); - cy.get(cesc("#\\/a2smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨mp,mq⟩"); - cy.get(cesc("#\\/simul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(e,f)"); - cy.get(cesc("#\\/simulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(e,f)"); - cy.get(cesc("#\\/simulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(e,f)"); - cy.get(cesc("#\\/ismul") + " .mjx-mrow") - .eq(0) - .should("have.text", "(e,f)m"); - cy.get(cesc("#\\/ismulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(e,f)"); - cy.get(cesc("#\\/ismulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(e,f)"); - cy.get(cesc("#\\/st2v2ssum") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(a,b)+(c,d)n"); - cy.get(cesc("#\\/st2v2ssumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(am+cn,bm+dn)"); - cy.get(cesc("#\\/st2v2ssumExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(am+cn,bm+dn)"); - cy.get(cesc("#\\/st2a2ssum") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(a,b)+⟨p,q⟩n"); - cy.get(cesc("#\\/st2a2ssumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(am+np,bm+nq)"); - cy.get(cesc("#\\/st2a2ssumExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(am+np,bm+nq)"); - cy.get(cesc("#\\/sv2a2ssum") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(c,d)+⟨p,q⟩n"); - cy.get(cesc("#\\/sv2a2ssumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(cm+np,dm+nq)"); - cy.get(cesc("#\\/sv2a2ssumExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(cm+np,dm+nq)"); - - cy.get(cesc("#\\/t3t3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g,h,i)+(g,h,i)"); - cy.get(cesc("#\\/t3t3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2g,2h,2i)"); - cy.get(cesc("#\\/v3v3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(j,k,l)+(j,k,l)"); - cy.get(cesc("#\\/v3v3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2j,2k,2l)"); - cy.get(cesc("#\\/a3a3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨r,s,t⟩+⟨r,s,t⟩"); - cy.get(cesc("#\\/a3a3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨2r,2s,2t⟩"); - cy.get(cesc("#\\/t3v3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g,h,i)+(j,k,l)"); - cy.get(cesc("#\\/t3v3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g+j,h+k,i+l)"); - cy.get(cesc("#\\/v3t3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(j,k,l)+(g,h,i)"); - cy.get(cesc("#\\/v3t3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g+j,h+k,i+l)"); - cy.get(cesc("#\\/t3a3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g,h,i)+⟨r,s,t⟩"); - cy.get(cesc("#\\/t3a3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g+r,h+s,i+t)"); - cy.get(cesc("#\\/a3t3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨r,s,t⟩+(g,h,i)"); - cy.get(cesc("#\\/a3t3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g+r,h+s,i+t)"); - cy.get(cesc("#\\/v3a3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "(j,k,l)+⟨r,s,t⟩"); - cy.get(cesc("#\\/v3a3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(j+r,k+s,l+t)"); - cy.get(cesc("#\\/a3v3sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨r,s,t⟩+(j,k,l)"); - cy.get(cesc("#\\/a3v3sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(j+r,k+s,l+t)"); - cy.get(cesc("#\\/t3v3diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g,h,i)βˆ’(j,k,l)"); - cy.get(cesc("#\\/t3v3diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gβˆ’j,hβˆ’k,iβˆ’l)"); - cy.get(cesc("#\\/v3t3diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "(j,k,l)βˆ’(g,h,i)"); - cy.get(cesc("#\\/v3t3diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’g+j,βˆ’h+k,βˆ’i+l)"); - cy.get(cesc("#\\/t3a3diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g,h,i)βˆ’βŸ¨r,s,t⟩"); - cy.get(cesc("#\\/t3a3diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gβˆ’r,hβˆ’s,iβˆ’t)"); - cy.get(cesc("#\\/a3t3diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨r,s,tβŸ©βˆ’(g,h,i)"); - cy.get(cesc("#\\/a3t3diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’g+r,βˆ’h+s,βˆ’i+t)"); - cy.get(cesc("#\\/v3a3diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "(j,k,l)βˆ’βŸ¨r,s,t⟩"); - cy.get(cesc("#\\/v3a3diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(jβˆ’r,kβˆ’s,lβˆ’t)"); - cy.get(cesc("#\\/a3v3diff") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨r,s,tβŸ©βˆ’(j,k,l)"); - cy.get(cesc("#\\/a3v3diffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’j+r,βˆ’k+s,βˆ’l+t)"); - cy.get(cesc("#\\/st3mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(g,h,i)"); - cy.get(cesc("#\\/st3mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gm,hm,im)"); - cy.get(cesc("#\\/st3mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gm,hm,im)"); - cy.get(cesc("#\\/t3smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g,h,i)m"); - cy.get(cesc("#\\/t3smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gm,hm,im)"); - cy.get(cesc("#\\/t3smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gm,hm,im)"); - cy.get(cesc("#\\/sv3mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(j,k,l)"); - cy.get(cesc("#\\/sv3mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(jm,km,lm)"); - cy.get(cesc("#\\/sv3mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(jm,km,lm)"); - cy.get(cesc("#\\/v3smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "(j,k,l)m"); - cy.get(cesc("#\\/v3smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(jm,km,lm)"); - cy.get(cesc("#\\/v3smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(jm,km,lm)"); - cy.get(cesc("#\\/sa3mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m⟨r,s,t⟩"); - cy.get(cesc("#\\/sa3mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨mr,ms,mt⟩"); - cy.get(cesc("#\\/sa3mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨mr,ms,mt⟩"); - cy.get(cesc("#\\/a3smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨r,s,t⟩m"); - cy.get(cesc("#\\/a3smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨mr,ms,mt⟩"); - cy.get(cesc("#\\/a3smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨mr,ms,mt⟩"); - cy.get(cesc("#\\/st3v3ssum") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(g,h,i)+(j,k,l)n"); - cy.get(cesc("#\\/st3v3ssumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gm+jn,hm+kn,im+ln)"); - cy.get(cesc("#\\/st3v3ssumExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gm+jn,hm+kn,im+ln)"); - cy.get(cesc("#\\/st3a3ssum") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(g,h,i)+⟨r,s,t⟩n"); - cy.get(cesc("#\\/st3a3ssumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gm+nr,hm+ns,im+nt)"); - cy.get(cesc("#\\/st3a3ssumExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(gm+nr,hm+ns,im+nt)"); - cy.get(cesc("#\\/sv3a3ssum") + " .mjx-mrow") - .eq(0) - .should("have.text", "m(j,k,l)+⟨r,s,t⟩n"); - cy.get(cesc("#\\/sv3a3ssumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(jm+nr,km+ns,lm+nt)"); - cy.get(cesc("#\\/sv3a3ssumExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(jm+nr,km+ns,lm+nt)"); - }); - - it("add and subtract matrices, multiply by scalar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

matrix22: \\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}

-

matrix21: \\begin{bmatrix}e\\\\f\\end{bmatrix}

-

matrix12: \\begin{bmatrix}g&h\\end{bmatrix}

-

Tuple2: (i,j)

-

Vector2: (k,l)

-

matrix22b: \\begin{bmatrix}n&o\\\\p&q\\end{bmatrix}

-

$matrix22+$matrix22

-

$matrix22+$matrix22

-

$matrix21+$matrix21

-

$matrix21+$matrix21

-

$matrix12+$matrix12

-

$matrix12+$matrix12

-

$matrix21+$tuple2

-

$matrix21+$tuple2

-

$matrix21+$vector2

-

$matrix21+$vector2

-

$matrix12+$tuple2

-

$matrix12+$tuple2

-

$matrix12+$vector2

-

$matrix12+$vector2

-

$matrix22+$matrix21

-

$matrix22+$matrix21

-

$matrix22+$matrix12

-

$matrix22+$matrix12

-

$matrix21+$matrix12

-

$matrix21+$matrix12

-

$matrix22+$matrix21+$matrix12+$matrix12+$matrix21+$matrix22

-

$matrix22+$matrix21+$matrix12+$matrix12+$matrix21+$matrix22

- -

m$matrix22

-

m$matrix22

-

m$matrix22

-

$matrix22 m

-

$matrix22 m

-

$matrix22 m

-

m$matrix21

-

m$matrix21

-

m$matrix21

-

$matrix21 m

-

$matrix21 m

-

$matrix21 m

-

m$matrix12

-

m$matrix12

-

m$matrix12

-

$matrix12 m

-

$matrix12 m

-

$matrix12 m

- - -

$matrix22+$matrix22b

-

$matrix22+$matrix22b

-

$matrix22-$matrix22b

-

$matrix22-$matrix22b

-

$matrix22+m$matrix22b

-

$matrix22+m$matrix22b

-

$matrix22+m$matrix22b

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m22m22sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]+[abcd]"); - cy.get(cesc("#\\/m22m22sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2a2b2c2d]"); - cy.get(cesc("#\\/m21m21sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ef]+[ef]"); - cy.get(cesc("#\\/m21m21sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2e2f]"); - cy.get(cesc("#\\/m12m12sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gh]+[gh]"); - cy.get(cesc("#\\/m12m12sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2g2h]"); - cy.get(cesc("#\\/m21t2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ef]+(i,j)"); - cy.get(cesc("#\\/m21t2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ef]+(i,j)"); - cy.get(cesc("#\\/m21v2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ef]+(k,l)"); - cy.get(cesc("#\\/m21v2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ef]+(k,l)"); - cy.get(cesc("#\\/m12t2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gh]+(i,j)"); - cy.get(cesc("#\\/m12t2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gh]+(i,j)"); - cy.get(cesc("#\\/m12v2sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gh]+(k,l)"); - cy.get(cesc("#\\/m12v2sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gh]+(k,l)"); - cy.get(cesc("#\\/m22m21sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]+[ef]"); - cy.get(cesc("#\\/m22m21sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ef]+[abcd]"); - cy.get(cesc("#\\/m22m12sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]+[gh]"); - cy.get(cesc("#\\/m22m12sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gh]+[abcd]"); - cy.get(cesc("#\\/m21m12sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ef]+[gh]"); - cy.get(cesc("#\\/m21m12sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gh]+[ef]"); - cy.get(cesc("#\\/m22m21m12m12m21m22sum") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]+[ef]+[gh]+[gh]+[ef]+[abcd]"); - cy.get(cesc("#\\/m22m21m12m12m21m22sumSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2g2h]+[2e2f]+[2a2b2c2d]"); - - cy.get(cesc("#\\/sm22mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m[abcd]"); - cy.get(cesc("#\\/sm22mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ambmcmdm]"); - cy.get(cesc("#\\/sm22mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ambmcmdm]"); - cy.get(cesc("#\\/m22smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]m"); - cy.get(cesc("#\\/m22smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ambmcmdm]"); - cy.get(cesc("#\\/m22smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ambmcmdm]"); - cy.get(cesc("#\\/sm21mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m[ef]"); - cy.get(cesc("#\\/sm21mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[emfm]"); - cy.get(cesc("#\\/sm21mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[emfm]"); - cy.get(cesc("#\\/m21smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ef]m"); - cy.get(cesc("#\\/m21smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[emfm]"); - cy.get(cesc("#\\/m21smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[emfm]"); - cy.get(cesc("#\\/sm12mul") + " .mjx-mrow") - .eq(0) - .should("have.text", "m[gh]"); - cy.get(cesc("#\\/sm12mulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gmhm]"); - cy.get(cesc("#\\/sm12mulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gmhm]"); - cy.get(cesc("#\\/m12smul") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gh]m"); - cy.get(cesc("#\\/m12smulSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gmhm]"); - cy.get(cesc("#\\/m12smulExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[gmhm]"); - - cy.get(cesc("#\\/m22m22b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]+[nopq]"); - cy.get(cesc("#\\/m22m22bSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[a+nb+oc+pd+q]"); - cy.get(cesc("#\\/m22m22bdiff") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]βˆ’[nopq]"); - cy.get(cesc("#\\/m22m22bdiffSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[aβˆ’nbβˆ’ocβˆ’pdβˆ’q]"); - cy.get(cesc("#\\/m22sm22b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]+m[nopq]"); - cy.get(cesc("#\\/m22sm22bSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[a+mnb+moc+mpd+mq]"); - cy.get(cesc("#\\/m22sm22bExpSimp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[a+mnb+moc+mpd+mq]"); - }); - - it("matrix multiplication", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

matrix22a: \\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}

-

matrix22b: \\begin{bmatrix}e&f\\\\g&h\\end{bmatrix}

-

matrix21a: \\begin{bmatrix}i\\\\j\\end{bmatrix}

-

matrix21b: \\begin{bmatrix}k\\\\l\\end{bmatrix}

-

matrix12a: \\begin{bmatrix}m&n\\end{bmatrix}

-

matrix12b: \\begin{bmatrix}o&p\\end{bmatrix}

-

$matrix22a$matrix22b

-

$matrix22a$matrix22b

-

$matrix22b$matrix22a

-

$matrix22b$matrix22a

-

$matrix21a$matrix21b

-

$matrix21a$matrix21b

-

$matrix12a$matrix12b

-

$matrix12a$matrix12b

-

$matrix21a$matrix12a

-

$matrix21a$matrix12a

-

$matrix12a$matrix21a

-

$matrix12a$matrix21a

-

$matrix22a$matrix21a$matrix12a$matrix22b$matrix21b$matrix12b

-

$matrix22a$matrix21a$matrix12a$matrix22b$matrix21b$matrix12b

-

\\begin{pmatrix}a e i k m o + a f i l m o + a g i k n o + a h i l n o + b e j k m o + b f j l m o + b g j k n o + b h j l n o & a e i k m p + a f i l m p + a g i k n p + a h i l n p + b e j k m p + b f j l m p + b g j k n p + b h j l n p\\\\ - c e i k m o + c f i l m o + c g i k n o + c h i l n o + d e j k m o + d f j l m o + d g j k n o + d h j l n o & c e i k m p + c f i l m p + c g i k n p + c h i l n p + d e j k m p + d f j l m p + d g j k n p + d h j l n p\\end{pmatrix}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m22am22b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd][efgh]"); - cy.get(cesc("#\\/m22am22bExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ae+bgaf+bhce+dgcf+dh]"); - cy.get(cesc("#\\/m22bm22a") + " .mjx-mrow") - .eq(0) - .should("have.text", "[efgh][abcd]"); - cy.get(cesc("#\\/m22bm22aExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ae+cfbe+dfag+chbg+dh]"); - cy.get(cesc("#\\/m21am21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ij][kl]"); - cy.get(cesc("#\\/m21am21bExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ij][kl]"); - cy.get(cesc("#\\/m12am12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[mn][op]"); - cy.get(cesc("#\\/m12am12bExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[mn][op]"); - cy.get(cesc("#\\/m21am12a") + " .mjx-mrow") - .eq(0) - .should("have.text", "[ij][mn]"); - cy.get(cesc("#\\/m21am12aExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[iminjmjn]"); - cy.get(cesc("#\\/m12am21a") + " .mjx-mrow") - .eq(0) - .should("have.text", "[mn][ij]"); - cy.get(cesc("#\\/m12am21aExp") + " .mjx-mrow") - .eq(0) - .should("have.text", "[im+jn]"); - cy.get(cesc("#\\/longmult") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd][ij][mn][efgh][kl][op]"); - cy.get(cesc("#\\/longmultExp") + " .mjx-mrow") - .eq(0) - .should( - "have.text", - "[aeikmo+afilmo+agikno+ahilno+bejkmo+bfjlmo+bgjkno+bhjlnoaeikmp+afilmp+agiknp+ahilnp+bejkmp+bfjlmp+bgjknp+bhjlnpceikmo+cfilmo+cgikno+chilno+dejkmo+dfjlmo+dgjkno+dhjlnoceikmp+cfilmp+cgiknp+chilnp+dejkmp+dfjlmp+dgjknp+dhjlnp]", - ); - cy.get(cesc("#\\/longMultResult") + " .mjx-mrow") - .eq(0) - .should( - "have.text", - "[aeikmo+afilmo+agikno+ahilno+bejkmo+bfjlmo+bgjkno+bhjlnoaeikmp+afilmp+agiknp+ahilnp+bejkmp+bfjlmp+bgjknp+bhjlnpceikmo+cfilmo+cgikno+chilno+dejkmo+dfjlmo+dgjkno+dhjlnoceikmp+cfilmp+cgiknp+chilnp+dejkmp+dfjlmp+dgjknp+dhjlnp]", - ); - }); - - it("matrix-vector multiplication", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

matrix22: \\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}

-

tuple2: (e,f)

-

vector2: (g,h)

-

alt vector2: ⟨p,q⟩

-

$matrix22$tuple2

-

$matrix22$tuple2

-

$tuple2$matrix22

-

$tuple2$matrix22

-

$matrix22$vector2

-

$matrix22$vector2

-

$vector2$matrix22

-

$vector2$matrix22

-

$matrix22$altvector2

-

$matrix22$altvector2

-

$altvector2$matrix22

-

$altvector2$matrix22

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m22t2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd](e,f)"); - cy.get(cesc("#\\/m22t2Exp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(ae+bf,ce+df)"); - cy.get(cesc("#\\/t2m22") + " .mjx-mrow") - .eq(0) - .should("have.text", "(e,f)[abcd]"); - cy.get(cesc("#\\/t2m22Exp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(e,f)[abcd]"); - cy.get(cesc("#\\/m22v2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd](g,h)"); - cy.get(cesc("#\\/m22v2Exp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(ag+bh,cg+dh)"); - cy.get(cesc("#\\/v2m22") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g,h)[abcd]"); - cy.get(cesc("#\\/v2m22Exp") + " .mjx-mrow") - .eq(0) - .should("have.text", "(g,h)[abcd]"); - cy.get(cesc("#\\/m22a2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[abcd]⟨p,q⟩"); - cy.get(cesc("#\\/m22a2Exp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨ap+bq,cp+dq⟩"); - cy.get(cesc("#\\/a2m22") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,q⟩[abcd]"); - cy.get(cesc("#\\/a2m22Exp") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨p,q⟩[abcd]"); - }); - - it("matrix and vector state variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

Originals: - \\begin{pmatrix} - 1 \\\\ 2 - \\end{pmatrix} - - - \\begin{pmatrix} - 1 & 2 - \\end{pmatrix} - - (1,2) - (1,2)' - (1,2)^T - 1,2 - (1,2) - (1,2)' - (1,2)^T - ⟨1,2⟩ - ⟨1,2⟩' - ⟨1,2⟩^T -

-

N dimensions: - - - - - - - - - - - - -

-

Vectors: - - - - - - - - - - - - -

-

Vectors as math: - - - - - - - - - - - - -

-

Vector x components: - - - - - - - - - - - - -

-

Vector y components: - - - - - - - - - - - - -

-

Vector x components b: - - - - - - - - - - - - -

-

Vector y components b: - - - - - - - - - - - - -

-

Matrix size: - - - - - - - - - - - - -

-

N rows: - - - - - - - - - - - - -

-

N columns: - - - - - - - - - - - - -

-

Matrices: - - - - - - - - - - - - -

-

Matrices as math: - - - - - - - - - - - - -

-

Row 1: - - - - - - - - - - - - -

-

Row 1 b: - - - - - - - - - - - - -

-

Row 1 c: - - - - - - - - - - - - -

-

Row 2: - - - - - - - - - - - - -

-

Row 2 b: - - - - - - - - - - - - -

-

Row 2 c: - - - - - - - - - - - - -

-

Column 1: - - - - - - - - - - - - -

-

Column 1 b: - - - - - - - - - - - - -

-

Column 2: - - - - - - - - - - - - -

-

Column 2 b: - - - - - - - - - - - - -

- -

Matrix entry 12: - - - - - - - - - - - - -

-

Matrix entry 12 b: - - - - - - - - - - - - -

-

Matrix entry 12 c: - - - - - - - - - - - - -

-

Matrix entry 12 d: - - - - - - - - - - - - -

-

Matrix entry 12 e: - - - - - - - - - - - - -

-

Matrix entry 12 f: - - - - - - - - - - - - -

-

Matrix entry 21: - - - - - - - - - - - - -

-

Matrix entry 21 b: - - - - - - - - - - - - -

-

Matrix entry 21 c: - - - - - - - - - - - - -

-

Matrix entry 21 d: - - - - - - - - - - - - -

-

Matrix entry 21 e: - - - - - - - - - - - - -

-

Matrix entry 21 f: - - - - - - - - - - - - -

- -

Graph vectors

- - - - - - - - - - - - - - - -

Change matrices

-

-

-

-

-

-

-

-

-

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/v1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v3") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v4") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)β€²"); - cy.get(cesc("#\\/v5") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)T"); - cy.get(cesc("#\\/v6") + " .mjx-mrow") - .eq(0) - .should("have.text", "1,2"); - cy.get(cesc("#\\/v7") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)β€²"); - cy.get(cesc("#\\/v9") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)T"); - cy.get(cesc("#\\/v10") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨1,2⟩"); - cy.get(cesc("#\\/v11") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨1,2βŸ©β€²"); - cy.get(cesc("#\\/v12") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨1,2⟩T"); - - cy.get(cesc("#\\/v1nd")).should("have.text", "2"); - cy.get(cesc("#\\/v2nd")).should("have.text", "2"); - cy.get(cesc("#\\/v3nd")).should("have.text", "2"); - cy.get(cesc("#\\/v4nd")).should("have.text", "2"); - cy.get(cesc("#\\/v5nd")).should("have.text", "2"); - cy.get(cesc("#\\/v6nd")).should("have.text", "2"); - cy.get(cesc("#\\/v7nd")).should("have.text", "2"); - cy.get(cesc("#\\/v8nd")).should("have.text", "2"); - cy.get(cesc("#\\/v9nd")).should("have.text", "2"); - cy.get(cesc("#\\/v10nd")).should("have.text", "2"); - cy.get(cesc("#\\/v11nd")).should("have.text", "2"); - cy.get(cesc("#\\/v12nd")).should("have.text", "2"); - - cy.get(cesc("#\\/v1v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v2v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v3v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v4v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v5v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v6v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v7v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v8v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v9v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v10v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v11v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v12v") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - - cy.get(cesc("#\\/v1vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v2vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v3vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v4vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v5vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v6vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v7vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v8vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v9vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v10vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v11vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/v12vm") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - - cy.get(cesc("#\\/v1x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v2x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v3x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v4x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v5x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v6x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v7x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v8x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v9x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v10x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v11x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v12x") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - - cy.get(cesc("#\\/v1xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v2xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v3xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v4xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v5xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v6xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v7xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v8xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v9xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v10xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v11xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/v12xb") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - - cy.get(cesc("#\\/v1y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v2y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v3y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v4y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v5y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v6y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v7y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v8y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v9y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v10y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v11y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v12y") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/v1yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v2yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v3yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v4yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v5yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v6yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v7yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v8yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v9yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v10yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v11yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v12yb") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/v1ms")).should("have.text", "2, 1"); - cy.get(cesc("#\\/v2ms")).should("have.text", "1, 2"); - cy.get(cesc("#\\/v3ms")).should("have.text", "2, 1"); - cy.get(cesc("#\\/v4ms")).should("have.text", "1, 2"); - cy.get(cesc("#\\/v5ms")).should("have.text", "1, 2"); - cy.get(cesc("#\\/v6ms")).should("have.text", "2, 1"); - cy.get(cesc("#\\/v7ms")).should("have.text", "2, 1"); - cy.get(cesc("#\\/v8ms")).should("have.text", "1, 2"); - cy.get(cesc("#\\/v9ms")).should("have.text", "1, 2"); - cy.get(cesc("#\\/v10ms")).should("have.text", "2, 1"); - cy.get(cesc("#\\/v11ms")).should("have.text", "1, 2"); - cy.get(cesc("#\\/v12ms")).should("have.text", "1, 2"); - - cy.get(cesc("#\\/v1nr")).should("have.text", "2"); - cy.get(cesc("#\\/v2nr")).should("have.text", "1"); - cy.get(cesc("#\\/v3nr")).should("have.text", "2"); - cy.get(cesc("#\\/v4nr")).should("have.text", "1"); - cy.get(cesc("#\\/v5nr")).should("have.text", "1"); - cy.get(cesc("#\\/v6nr")).should("have.text", "2"); - cy.get(cesc("#\\/v7nr")).should("have.text", "2"); - cy.get(cesc("#\\/v8nr")).should("have.text", "1"); - cy.get(cesc("#\\/v9nr")).should("have.text", "1"); - cy.get(cesc("#\\/v10nr")).should("have.text", "2"); - cy.get(cesc("#\\/v11nr")).should("have.text", "1"); - cy.get(cesc("#\\/v12nr")).should("have.text", "1"); - - cy.get(cesc("#\\/v1nc")).should("have.text", "1"); - cy.get(cesc("#\\/v2nc")).should("have.text", "2"); - cy.get(cesc("#\\/v3nc")).should("have.text", "1"); - cy.get(cesc("#\\/v4nc")).should("have.text", "2"); - cy.get(cesc("#\\/v5nc")).should("have.text", "2"); - cy.get(cesc("#\\/v6nc")).should("have.text", "1"); - cy.get(cesc("#\\/v7nc")).should("have.text", "1"); - cy.get(cesc("#\\/v8nc")).should("have.text", "2"); - cy.get(cesc("#\\/v9nc")).should("have.text", "2"); - cy.get(cesc("#\\/v10nc")).should("have.text", "1"); - cy.get(cesc("#\\/v11nc")).should("have.text", "2"); - cy.get(cesc("#\\/v12nc")).should("have.text", "2"); - - cy.get(cesc("#\\/v1m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v2m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v3m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v4m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v5m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v6m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v7m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v8m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v9m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v10m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v11m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v12m") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - - cy.get(cesc("#\\/v1mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v2mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v3mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v4mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v5mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v6mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v7mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v8mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v9mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v10mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v11mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v12mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - - cy.get(cesc("#\\/v1r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v2r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v3r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v4r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v5r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v6r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v7r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v8r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v9r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v10r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v11r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v12r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - - cy.get(cesc("#\\/v1r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v2r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v3r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v4r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v5r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v6r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v7r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v8r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v9r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v10r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v11r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v12r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - - cy.get(cesc("#\\/v1r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v2r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v3r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v4r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v5r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v6r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v7r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v8r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v9r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v10r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v11r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v12r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - - cy.get(cesc("#\\/v1r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v2r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v3r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v4r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v5r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v6r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v7r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v8r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v9r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v10r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v11r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v12r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - - cy.get(cesc("#\\/v1r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v2r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v3r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v4r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v5r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v6r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v7r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v8r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v9r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v10r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v11r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v12r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - - cy.get(cesc("#\\/v1r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v2r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v3r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v4r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v5r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v6r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v7r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v8r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v9r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v10r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v11r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v12r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - - cy.get(cesc("#\\/v1c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v2c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v3c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v4c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v5c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v6c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v7c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v8c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v9c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v10c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v11c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v12c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - - cy.get(cesc("#\\/v1c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v2c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v3c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v4c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v5c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v6c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v7c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v8c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v9c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v10c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/v11c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/v12c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - - cy.get(cesc("#\\/v1c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v2c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v3c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v4c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v5c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v6c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v7c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v8c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v9c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v10c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v11c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v12c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - - cy.get(cesc("#\\/v1c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v2c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v3c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v4c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v5c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v6c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v7c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v8c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v9c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v10c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/v11c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - cy.get(cesc("#\\/v12c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[2]"); - - cy.get(cesc("#\\/v1me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v2me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v3me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v4me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v5me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v6me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v7me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v8me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v9me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v10me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v11me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v12me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/v1me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v2me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v3me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v4me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v5me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v6me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v7me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v8me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v9me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v10me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v11me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v12me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/v1me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v2me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v3me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v4me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v5me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v6me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v7me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v8me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v9me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v10me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v11me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v12me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/v1me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v2me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v3me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v4me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v5me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v6me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v7me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v8me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v9me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v10me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v11me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v12me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/v1me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v2me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v3me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v4me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v5me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v6me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v7me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v8me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v9me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v10me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v11me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v12me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/v1me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v2me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v3me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v4me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v5me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v6me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v7me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v8me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v9me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v10me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v11me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v12me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/v1me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v2me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v3me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v4me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v5me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v6me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v7me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v8me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v9me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v10me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v11me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v12me21") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/v1me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v2me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v3me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v4me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v5me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v6me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v7me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v8me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v9me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v10me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v11me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v12me21b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/v1me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v2me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v3me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v4me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v5me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v6me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v7me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v8me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v9me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v10me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v11me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v12me21c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/v1me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v2me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v3me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v4me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v5me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v6me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v7me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v8me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v9me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v10me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v11me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v12me21d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/v1me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v2me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v3me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v4me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v5me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v6me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v7me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v8me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v9me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v10me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v11me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v12me21e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/v1me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v2me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v3me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v4me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v5me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v6me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v7me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v8me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v9me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v10me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/v11me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/v12me21f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.log("move vectors"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveVector", - componentName: "/v1vb", - args: { - headcoords: [2, 1], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v2vb", - args: { - headcoords: [2, 2], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v3vb", - args: { - headcoords: [2, 3], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v4vb", - args: { - headcoords: [2, 4], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v5vb", - args: { - headcoords: [2, 5], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v6vb", - args: { - headcoords: [2, 6], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v7vb", - args: { - headcoords: [2, 7], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v8vb", - args: { - headcoords: [2, 8], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v9vb", - args: { - headcoords: [2, 9], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v10vb", - args: { - headcoords: [2, 10], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v11vb", - args: { - headcoords: [2, 11], - }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v12vb", - args: { - headcoords: [2, 12], - }, - }); - }); - - cy.get(cesc("#\\/v12") + " .mjx-mrow").should( - "contain.text", - "⟨2,12⟩T", - ); - - cy.get(cesc("#\\/v1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[21]"); - cy.get(cesc("#\\/v2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[22]"); - cy.get(cesc("#\\/v3") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc("#\\/v4") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,4)β€²"); - cy.get(cesc("#\\/v5") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,5)T"); - cy.get(cesc("#\\/v6") + " .mjx-mrow") - .eq(0) - .should("have.text", "2,6"); - cy.get(cesc("#\\/v7") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,7)"); - cy.get(cesc("#\\/v8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,8)β€²"); - cy.get(cesc("#\\/v9") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,9)T"); - cy.get(cesc("#\\/v10") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨2,10⟩"); - cy.get(cesc("#\\/v11") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨2,11βŸ©β€²"); - cy.get(cesc("#\\/v12") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨2,12⟩T"); - - cy.log("change from matrix inputs"); - - cy.get(cesc("#\\/mi1_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi1_component_1_0") + " textarea").type( - "{end}{backspace}-1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2_component_0_1") + " textarea").type( - "{end}{backspace}-2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3_component_1_0") + " textarea").type( - "{end}{backspace}-3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi4_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi4_component_0_1") + " textarea").type( - "{end}{backspace}-4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi5_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi5_component_0_1") + " textarea").type( - "{end}{backspace}-5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi6_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi6_component_1_0") + " textarea").type( - "{end}{backspace}-6{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi7_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi7_component_1_0") + " textarea").type( - "{end}{backspace}-7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi8_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi8_component_0_1") + " textarea").type( - "{end}{backspace}-8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi9_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi9_component_0_1") + " textarea").type( - "{end}{backspace}-9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi10_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi10_component_1_0") + " textarea").type( - "{end}{backspace}{backspace}-10{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi11_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi11_component_0_1") + " textarea").type( - "{end}{backspace}{backspace}-11{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi12_component_0_0") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi12_component_0_1") + " textarea").type( - "{end}{backspace}{backspace}-12{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/v12") + " .mjx-mrow").should( - "contain.text", - "⟨3,βˆ’12⟩T", - ); - - cy.get(cesc("#\\/v1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[3βˆ’1]"); - cy.get(cesc("#\\/v2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[3βˆ’2]"); - cy.get(cesc("#\\/v3") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,βˆ’3)"); - cy.get(cesc("#\\/v4") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,βˆ’4)β€²"); - cy.get(cesc("#\\/v5") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,βˆ’5)T"); - cy.get(cesc("#\\/v6") + " .mjx-mrow") - .eq(0) - .should("have.text", "3,βˆ’6"); - cy.get(cesc("#\\/v7") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,βˆ’7)"); - cy.get(cesc("#\\/v8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,βˆ’8)β€²"); - cy.get(cesc("#\\/v9") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,βˆ’9)T"); - cy.get(cesc("#\\/v10") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨3,βˆ’10⟩"); - cy.get(cesc("#\\/v11") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨3,βˆ’11βŸ©β€²"); - cy.get(cesc("#\\/v12") + " .mjx-mrow") - .eq(0) - .should("have.text", "⟨3,βˆ’12⟩T"); - }); - - it("matrix state variables, non vector matrices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

Originals: - \\begin{pmatrix} - 1 & 2\\\\ - 3 & 4\\\\ - 5 & 6 - \\end{pmatrix} - - - 1 2 - 3 4 - 5 6 - - - 1 3 5 - 2 4 6 - -

-

Matrix size: - - - -

-

N rows: - - - -

-

N columns: - - - -

-

Matrices: - - - -

-

Matrices as math: - - - -

-

Row 1: - - - -

-

Row 1 b: - - - -

-

Row 1 c: - - - -

-

Row 2: - - - -

-

Row 2 b: - - - -

-

Row 2 c: - - - -

-

Row 3: - - - -

-

Row 3 b: - - - -

-

Row 3 c: - - - -

-

Row 4: - - - -

-

Row 4 b: - - - -

-

Row 4 c: - - - -

-

Column 1: - - - -

-

Column 1 b: - - - -

-

Column 2: - - - -

-

Column 2 b: - - - -

-

Column 3: - - - -

-

Column 3 b: - - - -

- -

Matrix entry 12: - - - -

-

Matrix entry 12 b: - - - -

-

Matrix entry 12 c: - - - -

-

Matrix entry 12 d: - - - -

-

Matrix entry 12 e: - - - -

-

Matrix entry 12 f: - - - -

-

Matrix entry 31: - - - -

-

Matrix entry 31 b: - - - -

-

Matrix entry 31 c: - - - -

-

Matrix entry 31 d: - - - -

-

Matrix entry 31 e: - - - -

-

Matrix entry 31 f: - - - -

-

Matrix entry 23: - - - -

-

Matrix entry 23 b: - - - -

-

Matrix entry 23 c: - - - -

-

Matrix entry 23 d: - - - -

-

Matrix entry 23 e: - - - -

-

Matrix entry 23 f: - - - -

- - -

Change matrices

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - - cy.get(cesc("#\\/m1ms")).should("have.text", "3, 2"); - cy.get(cesc("#\\/m2ms")).should("have.text", "3, 2"); - cy.get(cesc("#\\/m3ms")).should("have.text", "3, 2"); - - cy.get(cesc("#\\/m1nr")).should("have.text", "3"); - cy.get(cesc("#\\/m2nr")).should("have.text", "3"); - cy.get(cesc("#\\/m3nr")).should("have.text", "3"); - - cy.get(cesc("#\\/m1nc")).should("have.text", "2"); - cy.get(cesc("#\\/m2nc")).should("have.text", "2"); - cy.get(cesc("#\\/m3nc")).should("have.text", "2"); - - cy.get(cesc("#\\/m1m") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - cy.get(cesc("#\\/m2m") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - cy.get(cesc("#\\/m3m") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - - cy.get(cesc("#\\/m1mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - cy.get(cesc("#\\/m2mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - cy.get(cesc("#\\/m3mm") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣123456⎀βŽ₯⎦"); - - cy.get(cesc("#\\/m1r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/m2r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/m3r1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - - cy.get(cesc("#\\/m1r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/m2r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/m3r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - - cy.get(cesc("#\\/m1r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/m2r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - cy.get(cesc("#\\/m3r1c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[12]"); - - cy.get(cesc("#\\/m1r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - cy.get(cesc("#\\/m2r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - cy.get(cesc("#\\/m3r2") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - - cy.get(cesc("#\\/m1r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - cy.get(cesc("#\\/m2r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - cy.get(cesc("#\\/m3r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - - cy.get(cesc("#\\/m1r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - cy.get(cesc("#\\/m2r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - cy.get(cesc("#\\/m3r2c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[34]"); - - cy.get(cesc("#\\/m1r3") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - cy.get(cesc("#\\/m2r3") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - cy.get(cesc("#\\/m3r3") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - - cy.get(cesc("#\\/m1r3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - cy.get(cesc("#\\/m2r3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - cy.get(cesc("#\\/m3r3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - - cy.get(cesc("#\\/m1r3c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - cy.get(cesc("#\\/m2r3c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - cy.get(cesc("#\\/m3r3c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[56]"); - - cy.get(cesc("#\\/m1r4") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m2r4") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m3r4") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - - cy.get(cesc("#\\/m1r4b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m2r4b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m3r4b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - - cy.get(cesc("#\\/m1r4c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m2r4c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m3r4c") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - - cy.get(cesc("#\\/m1c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣135⎀βŽ₯⎦"); - cy.get(cesc("#\\/m2c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣135⎀βŽ₯⎦"); - cy.get(cesc("#\\/m3c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣135⎀βŽ₯⎦"); - - cy.get(cesc("#\\/m1c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣135⎀βŽ₯⎦"); - cy.get(cesc("#\\/m2c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣135⎀βŽ₯⎦"); - cy.get(cesc("#\\/m3c1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣135⎀βŽ₯⎦"); - - cy.get(cesc("#\\/m1c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣246⎀βŽ₯⎦"); - cy.get(cesc("#\\/m2c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣246⎀βŽ₯⎦"); - cy.get(cesc("#\\/m3c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣246⎀βŽ₯⎦"); - - cy.get(cesc("#\\/m1c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣246⎀βŽ₯⎦"); - cy.get(cesc("#\\/m2c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣246⎀βŽ₯⎦"); - cy.get(cesc("#\\/m3c2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣246⎀βŽ₯⎦"); - - cy.get(cesc("#\\/m1c3") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m2c3") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m3c3") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - - cy.get(cesc("#\\/m1c3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m2c3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - cy.get(cesc("#\\/m3c3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "[]"); - - cy.get(cesc("#\\/m1me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m2me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m3me12") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/m1me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m2me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m3me12b") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/m1me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m2me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m3me12c") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/m1me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m2me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m3me12d") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/m1me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m2me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m3me12e") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/m1me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m2me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/m3me12f") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/m1me31") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m2me31") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m3me31") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - - cy.get(cesc("#\\/m1me31b") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m2me31b") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m3me31b") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - - cy.get(cesc("#\\/m1me31c") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m2me31c") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m3me31c") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - - cy.get(cesc("#\\/m1me31d") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m2me31d") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m3me31d") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - - cy.get(cesc("#\\/m1me31e") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m2me31e") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m3me31e") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - - cy.get(cesc("#\\/m1me31f") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m2me31f") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/m3me31f") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - - cy.get(cesc("#\\/m1me23") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m2me23") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m3me23") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/m1me23b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m2me23b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m3me23b") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/m1me23c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m2me23c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m3me23c") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/m1me23d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m2me23d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m3me23d") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/m1me23e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m2me23e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m3me23e") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/m1me23f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m2me23f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m3me23f") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.log("change from matrix inputs"); - - cy.get(cesc("#\\/mi1_component_0_0") + " textarea").type( - "{end}{backspace}a{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi1_component_0_1") + " textarea").type( - "{end}{backspace}b{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi1_component_1_0") + " textarea").type( - "{end}{backspace}c{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi1_component_1_1") + " textarea").type( - "{end}{backspace}d{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi1_component_2_0") + " textarea").type( - "{end}{backspace}e{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi1_component_2_1") + " textarea").type( - "{end}{backspace}f{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mi2_component_0_0") + " textarea").type( - "{end}{backspace}g{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2_component_0_1") + " textarea").type( - "{end}{backspace}h{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2_component_1_0") + " textarea").type( - "{end}{backspace}i{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2_component_1_1") + " textarea").type( - "{end}{backspace}j{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2_component_2_0") + " textarea").type( - "{end}{backspace}k{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2_component_2_1") + " textarea").type( - "{end}{backspace}l{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mi3_component_0_0") + " textarea").type( - "{end}{backspace}m{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3_component_0_1") + " textarea").type( - "{end}{backspace}n{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3_component_1_0") + " textarea").type( - "{end}{backspace}o{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3_component_1_1") + " textarea").type( - "{end}{backspace}p{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3_component_2_0") + " textarea").type( - "{end}{backspace}q{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3_component_2_1") + " textarea").type( - "{end}{backspace}r{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m3") + " .mjx-mrow").should( - "contain.text", - "⎑⎒⎣mnopqr⎀βŽ₯⎦", - ); - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣abcdef⎀βŽ₯⎦"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣ghijkl⎀βŽ₯⎦"); - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "⎑⎒⎣mnopqr⎀βŽ₯⎦"); - }); - - it("simplify complex numbers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- i^2 - i^3 - i^4 - (1+i)(1-i) - aibici - (a+bi)(c+di) - (a+bi)(a-bi) - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/e1") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’1"); - cy.get(cesc("#\\/e2") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’i"); - cy.get(cesc("#\\/e3") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/e4") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/e5") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’abci"); - cy.get(cesc("#\\/e6") + " .mjx-mrow") - .eq(0) - .should("have.text", "ac+adi+bciβˆ’bd"); - cy.get(cesc("#\\/e7") + " .mjx-mrow") - .eq(0) - .should("have.text", "a2+b2"); - }); - - it("parse scientific notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

2E+3+3E+2 - 2E+3+3E+2 - 2E+3+3E+2 - 2E+3+3E+2

- - -

2E+3+3E+2 - 2E+3+3E+2 - 2E+3+3E+2 - 2E+3+3E+2

- -

2E3+3E2 - 2E3+3E2 - 2E3+3E2 - 2E3+3E2 -

- -

2E3+3E2 - 2E3+3E2 - 2E3+3E2 - 2E3+3E2 -

- -

- -

-

2E+3+3E+2

-

2E+3+3E+2

-

2E3+3E2

-

2E3+3E2

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "5E+5"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2300"); - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E+2002"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "2E+303"); - cy.get(cesc("#\\/m1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "5E+5"); - cy.get(cesc("#\\/m2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "2300"); - cy.get(cesc("#\\/m3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E+2002"); - cy.get(cesc("#\\/m4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "2E+303"); - - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2E3"); - cy.get(cesc("#\\/m6") + " .mjx-mrow") - .eq(0) - .should("have.text", "2300"); - cy.get(cesc("#\\/m7") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2000"); - cy.get(cesc("#\\/m8") + " .mjx-mrow") - .eq(0) - .should("have.text", "2E3+300"); - cy.get(cesc("#\\/m5a") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2E3"); - cy.get(cesc("#\\/m6a") + " .mjx-mrow") - .eq(0) - .should("have.text", "2300"); - cy.get(cesc("#\\/m7a") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2000"); - cy.get(cesc("#\\/m8a") + " .mjx-mrow") - .eq(0) - .should("have.text", "2E3+300"); - - cy.get(cesc("#\\/m9") + " .mjx-mrow") - .eq(0) - .should("have.text", "5E+5"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow") - .eq(0) - .should("have.text", "5E+5"); - cy.get(cesc("#\\/m10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2E3"); - cy.get(cesc("#\\/m10a") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2E3"); - - cy.get(cesc("#\\/p1")).click(); - cy.get(cesc("#\\/m9") + " .mjx-mrow").should("contain.text", "2E+303"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow").should("contain.text", "2E+303"); - cy.get(cesc("#\\/m10") + " .mjx-mrow").should( - "contain.text", - "2E3+300", - ); - cy.get(cesc("#\\/m10a") + " .mjx-mrow").should( - "contain.text", - "2E3+300", - ); - cy.get(cesc("#\\/m9") + " .mjx-mrow") - .eq(0) - .should("have.text", "2E+303"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow") - .eq(0) - .should("have.text", "2E+303"); - cy.get(cesc("#\\/m10") + " .mjx-mrow") - .eq(0) - .should("have.text", "2E3+300"); - cy.get(cesc("#\\/m10a") + " .mjx-mrow") - .eq(0) - .should("have.text", "2E3+300"); - - cy.get(cesc("#\\/p2")).click(); - cy.get(cesc("#\\/m9") + " .mjx-mrow").should("contain.text", "2300"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow").should("contain.text", "2300"); - cy.get(cesc("#\\/m10") + " .mjx-mrow").should("contain.text", "2300"); - cy.get(cesc("#\\/m10a") + " .mjx-mrow").should("contain.text", "2300"); - cy.get(cesc("#\\/m9") + " .mjx-mrow") - .eq(0) - .should("have.text", "2300"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow") - .eq(0) - .should("have.text", "2300"); - cy.get(cesc("#\\/m10") + " .mjx-mrow") - .eq(0) - .should("have.text", "2300"); - cy.get(cesc("#\\/m10a") + " .mjx-mrow") - .eq(0) - .should("have.text", "2300"); - - cy.get(cesc("#\\/p1")).click(); - cy.get(cesc("#\\/m9") + " .mjx-mrow").should("contain.text", "3E+2002"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow").should( - "contain.text", - "3E+2002", - ); - cy.get(cesc("#\\/m10") + " .mjx-mrow").should( - "contain.text", - "3E2+2000", - ); - cy.get(cesc("#\\/m10a") + " .mjx-mrow").should( - "contain.text", - "3E2+2000", - ); - cy.get(cesc("#\\/m9") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E+2002"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E+2002"); - cy.get(cesc("#\\/m10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2000"); - cy.get(cesc("#\\/m10a") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2000"); - - cy.get(cesc("#\\/p2")).click(); - cy.get(cesc("#\\/m9") + " .mjx-mrow").should("contain.text", "5E+5"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow").should("contain.text", "5E+5"); - cy.get(cesc("#\\/m10") + " .mjx-mrow").should( - "contain.text", - "3E2+2E3", - ); - cy.get(cesc("#\\/m10a") + " .mjx-mrow").should( - "contain.text", - "3E2+2E3", - ); - cy.get(cesc("#\\/m9") + " .mjx-mrow") - .eq(0) - .should("have.text", "5E+5"); - cy.get(cesc("#\\/m9a") + " .mjx-mrow") - .eq(0) - .should("have.text", "5E+5"); - cy.get(cesc("#\\/m10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2E3"); - cy.get(cesc("#\\/m10a") + " .mjx-mrow") - .eq(0) - .should("have.text", "3E2+2E3"); - }); - - it("subscripts and superscripts numbers to unicode text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

2x_1y_23+z_456-a_(7+8-90)

-

2x^1y^23+z^456-a^(7+8-90)

-

a^2 - b_2

-

$m1.text

-

$m2.text

-

$m3.text

-

aβ‚‚-bΒ²

- -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.get(cesc("#\\/m1t")).should( - "have.text", - "2 x₁ y₂₃ + z₄₅₆ - aβ‚‡β‚Šβ‚ˆβ‚‹β‚‰β‚€", - ); - cy.get(cesc("#\\/m2t")).should( - "have.text", - "2 xΒΉ yΒ²Β³ + z⁴⁡⁢ - a⁷⁺⁸⁻⁹⁰", - ); - cy.get(cesc("#\\/m3t")).should("have.text", "aΒ² - bβ‚‚"); - - cy.get(cesc("#\\/uv")).click(); - cy.get(cesc("#\\/m3t")).should("have.text", "aβ‚‚ - bΒ²"); - }); - - it("math in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $content1 - e^(-x^2) - - -

Anchor 1 coordinates: $math1.anchor

-

Anchor 2 coordinates: $math2.anchor

-

Change anchor 1 coordinates:

-

Change anchor 2 coordinates:

-

Position from anchor 1: $math1.positionFromAnchor

-

Position from anchor 2: $math2.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

-

Content 1: $math1

-

Content 2: $math2

-

Content 1

-

Content 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

-

- - `, - }, - "*", - ); - }); - - 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.get(cesc("#\\/pContent1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x23"); - cy.get(cesc("#\\/pContent2") + " .mjx-mrow") - .eq(0) - .should("have.text", "eβˆ’x2"); - - cy.log("move maths by dragging"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveMath", - componentName: "/math1", - args: { x: -2, y: 3 }, - }); - win.callAction1({ - actionName: "moveMath", - componentName: "/math2", - 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 maths 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 maths by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveMath", - componentName: "/math1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveMath", - componentName: "/math2", - 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("change content of math"); - cy.get(cesc("#\\/content1") + " textarea").type("{end}+5{enter}", { - force: true, - }); - cy.get(cesc("#\\/content2") + " textarea").type("{end}-a{enter}", { - force: true, - }); - - cy.get(cesc("#\\/pContent2") + " .mjx-mrow").should( - "contain.text", - "eβˆ’x2βˆ’a", - ); - - cy.get(cesc("#\\/pContent1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x23+5"); - cy.get(cesc("#\\/pContent2") + " .mjx-mrow") - .eq(0) - .should("have.text", "eβˆ’x2βˆ’a"); - - 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: "moveMath", - componentName: "/math1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveMath", - componentName: "/math2", - 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 math 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 maths by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveMath", - componentName: "/math1", - args: { x: 4, y: 6 }, - }); - win.callAction1({ - actionName: "moveMath", - componentName: "/math2", - 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 math 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("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 math 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 math 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 content only for math 1"); - cy.get(cesc("#\\/content2") + " textarea").type("{end}+y{enter}", { - force: true, - }); - cy.get(cesc("#\\/content1") + " textarea").type("{end}+z{enter}", { - force: true, - }); - - cy.get(cesc("#\\/pContent1") + " .mjx-mrow").should( - "contain.text", - "x23+5+z", - ); - - cy.get(cesc("#\\/pContent1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x23+5+z"); - cy.get(cesc("#\\/pContent2") + " .mjx-mrow") - .eq(0) - .should("have.text", "eβˆ’x2βˆ’a"); - }); - - it("math in graph, handle bad anchor coordinates", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x^2 - - - -

Anchor 1 coordinates: $math1.anchor

-

Change anchor 1 coordinates:

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.log("give good anchor coords"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(6,7){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(6,7)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - - cy.log("give bad anchor coords again"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}q{enter}", - { force: true }, + // wait until core is loaded + cy.waitUntil(() => + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + return stateVariables["/m1"]; + }), ); - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should("contain.text", "q"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") + cy.get(cesc("#\\/m1") + " .mjx-mrow") + .eq(0) + .should("have.text", "4+5"); + cy.get(cesc("#\\/m2") + " .mjx-mrow") + .eq(0) + .should("have.text", "x+6+7"); + cy.get(cesc("#\\/m4") + " .mjx-mrow") + .eq(0) + .should("have.text", "17"); + cy.get(cesc("#\\/m5") + " .mjx-mrow") .eq(0) - .should("have.text", "q"); + .should("have.text", "a+17"); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables["/m1"].stateValues.value).eqls(["+", 4, 5]); + expect(stateVariables["/m2"].stateValues.value).eqls([ + "+", + "x", + 6, + 7, + ]); + expect(stateVariables["/m3"].stateValues.value).eqls(["+", 6, 7]); + expect(stateVariables["/m4"].stateValues.value).eqls(17); + expect(stateVariables["/m5"].stateValues.value).eqls([ + "+", + "a", + 17, + ]); + }); }); it("color math via style", () => { @@ -11293,618 +642,4 @@ describe("Math Tag Tests", function () { .should("have.text", "(βˆ’5,βˆ’4)"); }); }); - - it("vec", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - \\vec{a} - vec a - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .should("have.text", "β†’a"); - cy.get(cesc("#\\/_math2") + " .mjx-mrow") - .eq(0) - .should("have.text", "β†’a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "vec", - "a", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "vec", - "a", - ]); - }); - }); - - it("line segment", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - \\overline{AB} - linesegment(A,B) - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .should("have.text", "Β―Β―Β―Β―Β―Β―Β―Β―AB"); - cy.get(cesc("#\\/_math2") + " .mjx-mrow") - .eq(0) - .should("have.text", "Β―Β―Β―Β―Β―Β―Β―Β―AB"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "linesegment", - "A", - "B", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "linesegment", - "A", - "B", - ]); - }); - }); - - it("perp", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - v \\perp u - v perp u - v^\\perp - v^perp - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .should("have.text", "vβŠ₯u"); - cy.get(cesc("#\\/_math2") + " .mjx-mrow") - .eq(0) - .should("have.text", "vβŠ₯u"); - cy.get(cesc("#\\/_math3") + " .mjx-mrow") - .eq(0) - .should("have.text", "vβŠ₯"); - cy.get(cesc("#\\/_math4") + " .mjx-mrow") - .eq(0) - .should("have.text", "vβŠ₯"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "perp", - "v", - "u", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "perp", - "v", - "u", - ]); - expect(stateVariables["/_math3"].stateValues.value).eqls([ - "^", - "v", - "perp", - ]); - expect(stateVariables["/_math4"].stateValues.value).eqls([ - "^", - "v", - "perp", - ]); - }); - }); - - it("parallel", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - v \\parallel u - v parallel u - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .should("have.text", "vβˆ₯u"); - cy.get(cesc("#\\/_math2") + " .mjx-mrow") - .eq(0) - .should("have.text", "vβˆ₯u"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "parallel", - "v", - "u", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "parallel", - "v", - "u", - ]); - }); - }); - - it("basic units", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- $5 - 25% - 60 deg - \\$5 - 25\\% - 60^{\\circ} - $5 - 25% - sin(90 deg) -

-

- $5 - 25% - 60 deg - sin(90 deg) -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/dol5") + " .mjx-mrow") - .eq(0) - .should("have.text", "$5"); - cy.get(cesc("#\\/perc25") + " .mjx-mrow") - .eq(0) - .should("have.text", "25%"); - cy.get(cesc("#\\/deg60") + " .mjx-mrow") - .eq(0) - .should("have.text", "60∘"); - cy.get(cesc("#\\/dol5b") + " .mjx-mrow") - .eq(0) - .should("have.text", "$5"); - cy.get(cesc("#\\/perc25b") + " .mjx-mrow") - .eq(0) - .should("have.text", "25%"); - cy.get(cesc("#\\/deg60b") + " .mjx-mrow") - .eq(0) - .should("have.text", "60∘"); - cy.get(cesc("#\\/dol5c") + " .mjx-mrow") - .eq(0) - .should("have.text", "$5"); - cy.get(cesc("#\\/perc25c") + " .mjx-mrow") - .eq(0) - .should("have.text", "25%"); - cy.get(cesc("#\\/sin90deg") + " .mjx-mrow") - .eq(0) - .should("have.text", "sin(90∘)"); - - cy.get(cesc("#\\/ndol5")).should("have.text", "5"); - cy.get(cesc("#\\/nperc25")).should("have.text", "0.25"); - cy.get(cesc("#\\/ndeg60")) - .invoke("text") - .then((text) => { - expect(parseFloat(text)).closeTo(Math.PI / 3, 1e-2); - }); - cy.get(cesc("#\\/nsin90deg")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/dol5"].stateValues.value).eqls([ - "unit", - "$", - 5, - ]); - expect(stateVariables["/perc25"].stateValues.value).eqls([ - "unit", - 25, - "%", - ]); - expect(stateVariables["/deg60"].stateValues.value).eqls([ - "unit", - 60, - "deg", - ]); - expect(stateVariables["/dol5b"].stateValues.value).eqls([ - "unit", - "$", - 5, - ]); - expect(stateVariables["/perc25b"].stateValues.value).eqls([ - "unit", - 25, - "%", - ]); - expect(stateVariables["/deg60b"].stateValues.value).eqls([ - "unit", - 60, - "deg", - ]); - expect(stateVariables["/dol5c"].stateValues.value).eqls([ - "unit", - "$", - 5, - ]); - expect(stateVariables["/perc25c"].stateValues.value).eqls([ - "unit", - 25, - "%", - ]); - expect(stateVariables["/ndol5"].stateValues.value).eq(5); - expect(stateVariables["/nperc25"].stateValues.value).eq(0.25); - expect(stateVariables["/ndeg60"].stateValues.value).closeTo( - Math.PI / 3, - 1e-14, - ); - expect(stateVariables["/nsin90deg"].stateValues.value).eq(1); - }); - }); - - it("some support for integral", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- int f(x) dx - int_a^b f(x) dx - \\int f(x) dx - \\int_a^b f(x) dx -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/indefint") + " .mjx-mrow") - .eq(0) - .should("have.text", "∫f(x)dx"); - cy.get(cesc("#\\/defint") + " .mjx-mrow") - .eq(0) - .should("have.text", "∫baf(x)dx"); - cy.get(cesc("#\\/indefintb") + " .mjx-mrow") - .eq(0) - .should("have.text", "∫f(x)dx"); - cy.get(cesc("#\\/defintb") + " .mjx-mrow") - .eq(0) - .should("have.text", "∫baf(x)dx"); - }); - - it("recover math values through latex state variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- (3,4) - (5,6) - sin(x)/exp(x) - \\frac{x}{y} - y/z - y=x+4 - sin(x)cos(x) - tan(x) cot(y) -

-

- $v.latex - $p.latex - $f.latex - $m.latex - $math.latex - $l.latex - $al.latex - $ml.latex -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/v2"].stateValues.value).eqls([ - "tuple", - 3, - 4, - ]); - expect(stateVariables["/p2"].stateValues.value).eqls([ - "tuple", - 5, - 6, - ]); - expect(stateVariables["/f2"].stateValues.value).eqls([ - "/", - ["apply", "sin", "x"], - ["apply", "exp", "x"], - ]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "/", - "x", - "y", - ]); - expect(stateVariables["/math2"].stateValues.value).eqls([ - "/", - "y", - "z", - ]); - expect(stateVariables["/l2"].stateValues.value).eqls([ - "=", - "y", - ["+", "x", 4], - ]); - expect(stateVariables["/al2"].stateValues.value).eqls([ - "list", - ["apply", "sin", "x"], - ["apply", "cos", "x"], - ]); - expect(stateVariables["/ml2"].stateValues.value).eqls([ - "list", - ["apply", "tan", "x"], - ["apply", "cot", "y"], - ]); - }); - }); - - it("Don't divide by vectors when inverting math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 3 - $n(3,4) - - - 3 - $n2*4 - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/n")).should("have.text", "3"); - cy.get(cesc2("#/n2")).should("have.text", "3"); - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,12)"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "12"); - - cy.get(cesc2("#/mi") + " textarea").type( - "{end}{shift+home}{backspace}(6,8){enter}", - { force: true }, - ); - cy.get(cesc2("#/mi2") + " textarea").type( - "{end}{shift+home}{backspace}8{enter}", - { force: true }, - ); - - cy.get(cesc2("#/n")).should("have.text", "3"); - cy.get(cesc2("#/n2")).should("have.text", "2"); - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,12)"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - }); - - it("support for some logical operators", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- not a - !a - \\lnot a - \\neg a - !a -

-

- a implies b - a β‡’ b - a ⟹ b - a \\implies b - a \\Longrightarrow b - a \\Rightarrow b -

- -

- a impliedby b - a ⇐ b - a ⟸ b - a \\impliedby b - a \\Longleftarrow b - a \\Leftarrow b -

- -

- a iff b - a ⇔ b - a ⟺ b - a \\iff b - a \\Longleftrightarrow b - a \\Leftrightarrow b -

- -

- a rightarrow b - a β†’ b - a ⟢ b - a \\to b - a \\longrightarrow b - a \\rightarrow b -

- -

- a leftarrow b - a ← b - a ⟡ b - a \\gets b - a \\longleftarrow b - a \\leftarrow b -

- -

- a leftrightarrow b - a ↔ b - a ⟷ b - a \\longleftrightarrow b - a \\leftrightarrow b -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let nots = ["/not_a", "/not_b", "/not_c", "/not_d", "/not_e"]; - let implies = [ - "/implies_a", - "/implies_b", - "/implies_c", - "/implies_d", - "/implies_e", - "/implies_f", - ]; - let impliedby = [ - "/impliedby_a", - "/impliedby_b", - "/impliedby_c", - "/impliedby_d", - "/impliedby_e", - "/impliedby_f", - ]; - let iff = ["/iff_a", "/iff_b", "/iff_c", "/iff_d", "/iff_e", "/iff_f"]; - - let rightarrow = [ - "/rightarrow_a", - "/rightarrow_b", - "/rightarrow_c", - "/rightarrow_d", - "/rightarrow_e", - "/rightarrow_f", - ]; - let leftarrow = [ - "/leftarrow_a", - "/leftarrow_b", - "/leftarrow_c", - "/leftarrow_d", - "/leftarrow_e", - "/leftarrow_f", - ]; - let leftrightarrow = [ - "/leftrightarrow_a", - "/leftrightarrow_b", - "/leftrightarrow_c", - "/leftrightarrow_d", - "/leftrightarrow_e", - ]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let id of nots) { - expect(stateVariables[id].stateValues.value).eqls(["not", "a"]); - } - for (let id of implies) { - expect(stateVariables[id].stateValues.value).eqls([ - "implies", - "a", - "b", - ]); - } - for (let id of impliedby) { - expect(stateVariables[id].stateValues.value).eqls([ - "impliedby", - "a", - "b", - ]); - } - for (let id of iff) { - expect(stateVariables[id].stateValues.value).eqls([ - "iff", - "a", - "b", - ]); - } - for (let id of rightarrow) { - expect(stateVariables[id].stateValues.value).eqls([ - "rightarrow", - "a", - "b", - ]); - } - for (let id of leftarrow) { - expect(stateVariables[id].stateValues.value).eqls([ - "leftarrow", - "a", - "b", - ]); - } - for (let id of leftrightarrow) { - expect(stateVariables[id].stateValues.value).eqls([ - "leftrightarrow", - "a", - "b", - ]); - } - }); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/mathinput.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/mathinput.cy.js index ae3f8075f..da13ce717 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/mathinput.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/mathinput.cy.js @@ -6,16823 +6,191 @@ describe("MathInput Tag Tests", function () { cy.visit("/"); }); - it("mathinput references", () => { - // A fairly involved test - // to check for bugs that have shown up after multiple manipulations - + it("natural input to sqrt", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a - - - - - - - - - +

a:

+

a2: $a.value{assignNames="a2"}

+

a3:

`, }, "*", ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+1", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+1", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); + cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); + cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "_"); - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).to.eq( - "\uFF3F", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/mi2"].stateValues.value).to.eq("\uFF3F"); + cy.get(cesc("#\\/a") + " textarea").type("sqrt4{enter}", { + force: true, }); - cy.log("Type 2 in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{end}2`, { force: true }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "x+12"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( + cy.get(cesc("#\\/a") + " .mq-editable-field").should( "contain.text", - "x+12", + "√4", ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) + cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "√4"); + cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2"); + + cy.get(cesc("#\\/a") + " .mq-editable-field") .invoke("text") .then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", + "√4", ); }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc(`#\\/v2`)) + cy.get(cesc("#\\/a2")) .find(".mjx-mrow") .eq(0) .invoke("text") .then((text) => { - expect(text.trim()).equal("_"); + expect(text.trim()).equal("√4"); }); - cy.get(cesc(`#\\/iv2`)) + cy.get(cesc("#\\/a3")) .find(".mjx-mrow") .eq(0) .invoke("text") .then((text) => { - expect(text.trim()).equal("_"); + expect(text.trim()).equal("2"); }); + }); + + it("check ignoreUpdate bug 1", () => { + // if set core to delay 1 second on updates + // then the refresh on blur (from the focus field recoil atoms changing) + // would cause rendererValue.current to be changed to the old SV value + // as the update wouldn't be ignored - cy.log("Test internal values are set to the correct values"); cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - 12, - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - 12, - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).to.eq( - "\uFF3F", + win.postMessage( + { + doenetML: ` +

a

+

n:

+

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

+ `, + }, + "*", ); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/mi2"].stateValues.value).to.eq("\uFF3F"); }); - // cy.log("Pressing Escape undoes change"); - // cy.get(cesc('#\\/mi1_input')).type(`{esc}`); + cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + + // by highlighting and typing a number, we make sure the rendererValue changes directly + // from 10 to 20 and back to 10 (without other changes that would hide the bug) + cy.get(cesc("#\\/n") + " textarea") + .type("{home}{shift+rightArrow}2", { force: true }) + .blur(); + cy.get(cesc("#\\/n2")).should("contain.text", "20"); + + cy.get(cesc("#\\/n") + " textarea") + .type("{home}{shift+rightArrow}1", { force: true }) + .blur(); + cy.get(cesc("#\\/n2")).should("contain.text", "10"); + }); - // cy.log('Test values displayed in browser') - // cy.get(cesc('#\\/mi1_input')).should('have.value', 'x + 1'); - // cy.get(cesc(`#\\/mi1a`) + ` textarea`).should('have.value', 'x + 1'); - // cy.get(cesc('#\\/mi2_input')).should('have.value', ''); + it("check ignoreUpdate bug 2", () => { + // if set core to delay 1 second on updates + // the extra update from focusing another mathinput wasn't being ignored + // leading rendererValue to get out of sync - // cy.get(cesc(`#\\/v1`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('x+1') - // }); - // cy.get(cesc(`#\\/iv1`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('x+1') - // }); + cy.window().then(async (win) => { + win.postMessage( + { + doenetML: ` + a - // cy.log('Test internal values are set to the correct values') - // cy.window().then(async (win) => { - // stateVariables = await win.returnAllStateVariables1(); - // expect(stateVariables['/mi1'].stateValues.immediateValue).eqls(['+', 'x', 1]); - // expect(stateVariables['/mi1a'].stateValues.immediateValue).eqls(['+', 'x', 1]); - // expect(stateVariables['/mi2'].stateValues.immediateValue).to.eq('\uFF3F'); - // expect(stateVariables['/mi1'].stateValues.value).eqls(['+', 'x', 1]); - // expect(stateVariables['/mi1a'].stateValues.value).eqls(['+', 'x', 1]); - // expect(stateVariables['/mi2'].stateValues.value).to.eq('\uFF3F'); - // }); +

c:

+

c2: $c.value{assignNames="c2"}

+

d:

- cy.log("Changing to 3 in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{end}{backspace}3`, { - force: true, + `, + }, + "*", + ); }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "x+13"); - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "x+13", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "x+13", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+13", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+13", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); + cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+13"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") + cy.get(cesc("#\\/c2") + " .mjx-mrow") .eq(0) .invoke("text") .then((text) => { - expect(text.trim()).equal("x+13"); + expect(text).eq("x"); }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") + + cy.get(cesc("#\\/c") + " textarea").type("{end}y{enter}", { + force: true, + }); + cy.get(cesc("#\\/d") + " textarea").focus(); + + cy.get(cesc("#\\/c2")).should("contain.text", "xy"); + cy.get(cesc("#\\/c") + " .mq-editable-field").should( + "contain.text", + "xy", + ); + cy.get(cesc("#\\/c2") + " .mjx-mrow") .eq(0) .invoke("text") .then((text) => { - expect(text.trim()).equal("οΌΏ"); + expect(text).eq("xy"); }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") + + // need next update to go back to x for the bug to be revealed + cy.get(cesc("#\\/c") + " textarea").type("{end}{backspace}{enter}", { + force: true, + }); + cy.get(cesc("#\\/c2")).should("not.contain.text", "xy"); + cy.get(cesc("#\\/c") + " .mq-editable-field").should( + "contain.text", + "x", + ); + cy.get(cesc("#\\/c2") + " .mjx-mrow") .eq(0) .invoke("text") .then((text) => { - expect(text.trim()).equal("οΌΏ"); + expect(text).eq("x"); }); + }); + + it("set value from immediateValue on reload", () => { + let doenetML = ` +

+ +

value: $n

+

immediate value: $n.immediateValue

+ `; + + cy.get("#testRunner_toggleControls").click(); + cy.get("#testRunner_allowLocalState").click(); + cy.wait(100); + cy.get("#testRunner_toggleControls").click(); - cy.log("Test internal values are set to the correct values"); cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - 13, - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - 13, - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).to.eq( - "\uFF3F", + win.postMessage( + { + doenetML, + }, + "*", ); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect(stateVariables["/mi2"].stateValues.value).to.eq("\uFF3F"); }); - cy.log("Pressing Enter in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{enter}`, { force: true }); - cy.get(cesc(`#\\/v1`)).should("contain.text", "x+13"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+13", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+13", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); + cy.get(cesc("#\\/n") + " textarea").type("1", { force: true }); - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "x+13"); - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "x+13"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "x+13"); - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "x+13"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") + cy.get(cesc("#\\/piv") + " .mjx-mrow").should("contain.text", "1"); + cy.get(cesc("#\\/piv") + " .mjx-mrow") .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+13"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") + .should("have.text", "1"); + cy.get(cesc("#\\/pv") + " .mjx-mrow") .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+13"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+13"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+13"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - 13, - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - 13, - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).to.eq( - "\uFF3F", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - 13, - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - 13, - ]); - expect(stateVariables["/mi2"].stateValues.value).to.eq("\uFF3F"); - }); - - // cy.log("Pressing Escape does not undo change"); - // cy.get(cesc('#\\/mi1_input')).type(`{esc}`); - - // cy.log('Test values displayed in browser') - // cy.get(cesc('#\\/mi1_input')).should('have.value', 'x + 13'); - // cy.get(cesc(`#\\/mi1a`) + ` textarea`).should('have.value', 'x + 13'); - // cy.get(cesc('#\\/mi2_input')).should('have.value', ''); - - // cy.get(cesc(`#\\/v1`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('x+13') - // }); - // cy.get(cesc(`#\\/iv1`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('x+13') - // }); - - // cy.log('Test internal values are set to the correct values') - // cy.window().then(async (win) => { - // stateVariables = await win.returnAllStateVariables1(); - // expect(stateVariables['/mi1'].stateValues.immediateValue).eqls(['+', 'x', 13]); - // expect(stateVariables['/mi1a'].stateValues.immediateValue).eqls(['+', 'x', 13]); - // expect(stateVariables['/mi2'].stateValues.immediateValue).to.eq('\uFF3F'); - // expect(stateVariables['/mi1'].stateValues.value).eqls(['+', 'x', 13]); - // expect(stateVariables['/mi1a'].stateValues.value).eqls(['+', 'x', 13]); - // expect(stateVariables['/mi2'].stateValues.value).to.eq('\uFF3F'); - // }); - - cy.log("Erasing 13 and typing y second mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").blur(); - cy.get(cesc(`#\\/mi1a`) + ` textarea`).type( - `{end}{backspace}{backspace}y`, - { force: true }, - ); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "x+y"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "x+y", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "x+y", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/iv1a`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+13"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+13"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).to.eq( - "\uFF3F", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - 13, - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - 13, - ]); - expect(stateVariables["/mi2"].stateValues.value).to.eq("\uFF3F"); - }); - - cy.log("Changing focus to first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").focus(); - cy.get(cesc(`#\\/v1`)).should("contain.text", "x+y"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "x+y", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "x+y", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "x+y"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).to.eq( - "\uFF3F", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.value).to.eq("\uFF3F"); - }); - - // cy.log("Changing escape doesn't do anything"); - // cy.get(cesc('#\\/mi1_input')).type("{esc}"); - - // cy.log('Test values displayed in browser') - // cy.get(cesc('#\\/mi1_input')).should('have.value', 'x + y'); - // cy.get(cesc(`#\\/mi1a`) + ` textarea`).should('have.value', 'x + y'); - // cy.get(cesc('#\\/mi2_input')).should('have.value', ''); - - // cy.get(cesc(`#\\/v1`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('x+y') - // }); - // cy.get(cesc(`#\\/iv1`)).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('x+y') - // }); - - // cy.log('Test internal values are set to the correct values') - // cy.window().then(async (win) => { - // stateVariables = await win.returnAllStateVariables1(); - // expect(stateVariables['/mi1'].stateValues.immediateValue).eqls(['+', 'x', 'y']); - // expect(stateVariables['/mi1a'].stateValues.immediateValue).eqls(['+', 'x', 'y']); - // expect(stateVariables['/mi2'].stateValues.immediateValue).to.eq('\uFF3F'); - // expect(stateVariables['/mi1'].stateValues.value).eqls(['+', 'x', 'y']); - // expect(stateVariables['/mi1a'].stateValues.value).eqls(['+', 'x', 'y']); - // expect(stateVariables['/mi2'].stateValues.value).to.eq('\uFF3F'); - // }); - - // pq in third input - - cy.log("Typing pq in third mathinput"); - cy.get(cesc("#\\/mi2") + " textarea").type(`pq`, { force: true }); - cy.get(cesc(`#\\/iv2`)).should("contain.text", "pq"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "pq", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "pq", - ); - }); - - cy.get(cesc(`#\\/iv2`) + ` .mjx-mrow`).should("contain.text", "pq"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "p", - "q", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.value).to.eq("\uFF3F"); - }); - - // press enter in mathinput 3 - - cy.log("Pressing enter in third mathinput"); - cy.get(cesc("#\\/mi2") + " textarea").type(`{enter}`, { force: true }); - cy.get(cesc(`#\\/v2`)).should("contain.text", "pq"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+y", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "pq", - ); - }); - - cy.get(cesc(`#\\/v2`) + ` .mjx-mrow`).should("contain.text", "pq"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "p", - "q", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "p", - "q", - ]); - }); - - // type abc in mathinput 2 - - cy.log("Typing abc in second mathinput"); - cy.get(cesc(`#\\/mi1a`) + ` textarea`).type( - `{ctrl+home}{shift+end}{backspace}abc`, - { force: true }, - ); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "abc"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "abc", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "abc", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abc", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abc", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "pq", - ); - }); - - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "abc"); - cy.get(cesc(`#\\/iv1a`) + ` .mjx-mrow`).should("contain.text", "abc"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+y"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "p", - "q", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "p", - "q", - ]); - }); - - // leave mathinput 2 - - cy.log("Leave second mathinput"); - cy.get(cesc(`#\\/mi1a`) + ` textarea`).blur(); - cy.get(cesc(`#\\/v1`)).should("contain.text", "abc"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "abc", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "abc", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abc", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abc", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "pq", - ); - }); - - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "abc"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "abc"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "p", - "q", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "p", - "q", - ]); - }); - - // Enter abc in mathinput 1 - - cy.log("Enter abc in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}`, - { force: true }, - ); - // pause after deleting so can detect change (given going from abc back to abc) - cy.get(cesc(`#\\/iv1`)).should("contain.text", "οΌΏ"); - cy.get(cesc("#\\/mi1") + " textarea").type(`abc{enter}`, { - force: true, - }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "abc"); - cy.wait(100); // since can't detect effect of {enter} given that v1 is already abc - cy.get(cesc(`#\\/v1`)).should("contain.text", "abc"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "abc", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "abc", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abc", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abc", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "pq", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "p", - "q", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "p", - "q", - ]); - }); - - // type u/v in mathinput 3 - - cy.log("Typing u/v in third mathinput"); - cy.get(cesc("#\\/mi2") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}u/v`, - { force: true }, - ); - cy.get(cesc(`#\\/iv2`)).should("contain.text", "uv"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "uv", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abc", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abc", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "uv", - ); - }); - - cy.get(cesc(`#\\/iv2`) + ` .mjx-mrow`).should("contain.text", "uv"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("pq"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "/", - "u", - "v", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "p", - "q", - ]); - }); - - // type d in mathinput 1 - - cy.log("Typing d in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{end}d`, { force: true }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "abcd"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "abcd", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "abcd", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abcd", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abcd", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "uv", - ); - }); - - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "abcd"); - cy.get(cesc(`#\\/v2`) + ` .mjx-mrow`).should("contain.text", "uv"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abcd"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abc"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abcd"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - "d", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - "d", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "/", - "u", - "v", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "/", - "u", - "v", - ]); - }); - - cy.log("Leaving first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").blur(); - cy.get(cesc(`#\\/v1`)).should("contain.text", "abcd"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "abcd", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "abcd", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abcd", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "abcd", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "uv", - ); - }); - - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "abcd"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "abcd"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abcd"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abcd"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abcd"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abcd"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - "d", - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - "c", - "d", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "/", - "u", - "v", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - "d", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - "d", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "/", - "u", - "v", - ]); - }); - - cy.log("Clearing second mathinput"); - cy.get(cesc(`#\\/mi1a`) + ` textarea`).type( - "{ctrl+home}{shift+end}{backspace}", - { force: true }, - ); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "\uFF3F"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "not.contain.text", - "a", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "not.contain.text", - "a", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "uv", - ); - }); - - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "\uFF3F"); - cy.get(cesc(`#\\/iv1a`) + ` .mjx-mrow`).should( - "contain.text", - "\uFF3F", - ); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abcd"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uFF3F"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("abcd"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uFF3F"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).to.eq( - "\uFF3F", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).to.eq( - "\uFF3F", - ); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "/", - "u", - "v", - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - "d", - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "*", - "a", - "b", - "c", - "d", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "/", - "u", - "v", - ]); - }); - - cy.log("Focus on third mathinput"); - cy.get(cesc("#\\/mi2") + " textarea").focus(); - cy.get(cesc(`#\\/v1`)).should("contain.text", "\uFF3F"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "not.contain.text", - "abcd", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "not.contain.text", - "abcd", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "uv", - ); - }); - - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "\uFF3F"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "\uFF3F"); - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uFF3F"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uFF3F"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uFF3F"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uFF3F"); - }); - cy.get(cesc(`#\\/v2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - cy.get(cesc(`#\\/iv2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).to.eq( - "\uFF3F", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).to.eq( - "\uFF3F", - ); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "/", - "u", - "v", - ]); - expect(stateVariables["/mi1"].stateValues.value).to.eq("\uFF3F"); - expect(stateVariables["/mi1a"].stateValues.value).to.eq("\uFF3F"); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "/", - "u", - "v", - ]); - }); - }); - - it("mathinput references with invalid math expressions", () => { - let doenetML = ` - a - - - - - - -

$bi.value{assignNames="b"}

- `; - - 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, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("οΌΏ"); - }); - - cy.log("Type x~ in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type(`x`, { force: true }); - // pause so that can detect change - cy.get(cesc(`#\\/iv1`)).should("contain.text", "x"); - cy.get(cesc("#\\/mi1") + " textarea") - .type(`~`, { force: true }) - .blur(); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "\uFF3F"); - - // since v1 was already invalid, can't be sure when have waited long enough - // so click boolean input and wait for its effect to take - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "x~", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "x~", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x~", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x~", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("οΌΏ"); - }); - - // pause 2 seconds to make sure 1 second debounce for saving was satisfied - cy.wait(2000); - - cy.log("reload page"); - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // the DOM will display even before core is ready - // so to make sure core has loaded, click boolean and wait for it to change - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "x~", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "x~", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x~", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x~", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("οΌΏ"); - }); - - cy.log("Delete ~ and add -y in copied mathinput"); - cy.get(cesc("#\\/mi1a") + " textarea").type(`{end}{backspace}-y`, { - force: true, - }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "xβˆ’y"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("οΌΏ"); - }); - - cy.log("blur"); - cy.get(cesc("#\\/mi1a") + " textarea").blur(); - cy.get(cesc(`#\\/v1`)).should("contain.text", "xβˆ’y"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "xβˆ’y"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "xβˆ’y"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - ["-", "y"], - ]); - }); - - cy.log("Add & in copied mathinput"); - cy.get(cesc("#\\/mi1a") + " textarea").type(`{end}@`, { force: true }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "\uFF3F"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y@", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y@", - ); - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "οΌΏ"); - cy.get(cesc(`#\\/iv1a`) + ` .mjx-mrow`).should("contain.text", "οΌΏ"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y@", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y@", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - ["-", "y"], - ]); - }); - - cy.log("Delete @ and add *z in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{end}`, { force: true }); - cy.get(cesc("#\\/mi1") + " textarea").type(`{end}{backspace}*z`, { - force: true, - }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "xβˆ’yz"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’yΒ·z", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’yΒ·z", - ); - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yz"); - cy.get(cesc(`#\\/iv1a`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yz"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·z", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·z", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("οΌΏ"); - }); - - cy.log("Press enter"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{enter}`, { force: true }); - - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yz"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yz"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·z", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·z", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - }); - }); - - it("mathinput references with incomplete math expressions", () => { - let doenetML = ` - a - - - - - - -

$bi.value{assignNames="b"}

- `; - - 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, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls( - "οΌΏ", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("οΌΏ"); - }); - - cy.log("Type x- in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type(`x`, { force: true }); - // pause so that can detect change - cy.get(cesc(`#\\/iv1`)).should("contain.text", "x"); - cy.get(cesc("#\\/mi1") + " textarea") - .type(`-`, { force: true }) - .blur(); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "x-"); - - // since v1 was already invalid, can't be sure when have waited long enough - // so click boolean input and wait for its effect to take - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls( - "x-", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls( - "x-", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls("x-"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("x-"); - }); - - // pause 2 seconds to make sure 1 second debounce for saving was satisfied - cy.wait(2000); - - cy.log("reload page"); - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // the DOM will display even before core is ready - // so to make sure core has loaded, click boolean and wait for it to change - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls( - "x-", - ); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls( - "x-", - ); - expect(stateVariables["/mi1"].stateValues.value).eqls("x-"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("x-"); - }); - - cy.log("Add y in copied mathinput"); - cy.get(cesc("#\\/mi1a") + " textarea").type(`{end}y`, { force: true }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "xβˆ’y"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x-"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls("x-"); - expect(stateVariables["/mi1a"].stateValues.value).eqls("x-"); - }); - - cy.log("blur"); - cy.get(cesc("#\\/mi1a") + " textarea").blur(); - cy.get(cesc(`#\\/v1`)).should("contain.text", "xβˆ’y"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "xβˆ’y"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "xβˆ’y"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’y", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’y", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - ["-", "y"], - ]); - }); - - cy.log("Add * in copied mathinput"); - cy.get(cesc("#\\/mi1a") + " textarea").type(`{end}*`, { force: true }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "\uFF3F"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’yΒ·", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’yΒ·", - ); - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yοΌΏ"); - cy.get(cesc(`#\\/iv1a`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yοΌΏ"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yοΌΏ"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’y"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yοΌΏ"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "οΌΏ"]], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "οΌΏ"]], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - ["-", "y"], - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - ["-", "y"], - ]); - }); - - cy.log("Add z in first mathinput"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{end}`, { force: true }); - cy.get(cesc("#\\/mi1") + " textarea").type(`{end}z`, { force: true }); - cy.get(cesc(`#\\/iv1`)).should("contain.text", "xβˆ’yz"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’yΒ·z", - ); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`).should( - "contain.text", - "xβˆ’yΒ·z", - ); - cy.get(cesc(`#\\/iv1`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yz"); - cy.get(cesc(`#\\/iv1a`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yz"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·z", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·z", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yοΌΏ"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yοΌΏ"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - ["-", ["*", "y", "οΌΏ"]], - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - ["-", ["*", "y", "οΌΏ"]], - ]); - }); - - cy.log("Press enter"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{enter}`, { force: true }); - - cy.get(cesc(`#\\/v1`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yz"); - cy.get(cesc(`#\\/v1a`) + ` .mjx-mrow`).should("contain.text", "xβˆ’yz"); - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·z", - ); - }); - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xβˆ’yΒ·z", - ); - }); - - cy.get(cesc(`#\\/v1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - cy.get(cesc(`#\\/iv1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - cy.get(cesc(`#\\/v1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - cy.get(cesc(`#\\/iv1a`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xβˆ’yz"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1a"].stateValues.immediateValue).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - expect(stateVariables["/mi1a"].stateValues.value).eqls([ - "+", - "x", - ["-", ["*", "y", "z"]], - ]); - }); - }); - - it("downstream from mathinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Original math: 1+2x

-

MathInput based on math:

-

Copied mathinput:

-

Value of original mathinput:

-

Immediate value of original mathinput:

-

Value of copied mathinput:

-

Immediate value of copied mathinput:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2x", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2x", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - }); - - cy.log("type new values"); - cy.get(cesc("#\\/mi1") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}xy`, - { force: true, delay: 100 }, - ); - - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{enter}`, { force: true }); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "xy"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - }); - - cy.log("enter new values in referenced"); - cy.get(cesc(`#\\/mi2`) + ` textarea`) - .type(`{end}{backspace}{backspace}qr{enter}`, { force: true }) - .blur(); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - }); - - cy.reload(); - - cy.log("prefill ignored"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b -

Original math: 1+2x

-

MathInput based on math:

-

Copied mathinput:

-

Value of original mathinput:

-

Immediate value of original mathinput:

-

Value of copied mathinput:

-

Immediate value of copied mathinput:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "b"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2x", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2x", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - }); - - cy.reload(); - - cy.log("normal downstream rules apply"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c -

Original math: 1+3x

-

MathInput based on math:

-

Copied mathinput:

-

Value of original mathinput:

-

Immediate value of original mathinput:

-

Value of copied mathinput:

-

Immediate value of copied mathinput:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "c"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3x+1", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3x+1", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "*", - 3, - "x", - ]); - }); - - cy.log("type new values"); - cy.get(cesc("#\\/mi1") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}xy{enter}`, - { force: true, delay: 100 }, - ); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "+", - ["*", "x", "y"], - -1, - ]); - }); - - cy.log("enter new values in reffed"); - cy.get(cesc(`#\\/mi2`) + ` textarea`).type( - `{end}{backspace}{backspace}qr{enter}`, - { force: true }, - ); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "+", - ["*", "q", "r"], - -1, - ]); - }); - }); - - it("downstream from mathinput via child", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Original math: 1+2x

-

MathInput based on math: $_math1

-

Copied mathinput:

-

Value of original mathinput:

-

Immediate value of original mathinput:

-

Value of copied mathinput:

-

Immediate value of copied mathinput:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2x", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2x", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - }); - - cy.log("type new values"); - cy.get(cesc("#\\/mi1") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}xy`, - { force: true, delay: 100 }, - ); - - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{enter}`, { force: true }); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "xy"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - }); - - cy.log("enter new values in referenced"); - cy.get(cesc(`#\\/mi2`) + ` textarea`) - .type(`{end}{backspace}{backspace}qr{enter}`, { force: true }) - .blur(); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - }); - - cy.reload(); - - cy.log("prefill ignored"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b -

Original math: 1+2x

-

MathInput based on math: $_math1

-

Copied mathinput:

-

Value of original mathinput:

-

Immediate value of original mathinput:

-

Value of copied mathinput:

-

Immediate value of copied mathinput:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "b"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2x", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2x", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x"], - ]); - }); - - cy.reload(); - - cy.log("base on combination children including string"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - bb -

Original math: x

-

MathInput based on math and strings: 2$_math1+1

-

Value mathinput:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "bb"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2x+1", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc(`#\\/value`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x+1"); - }); - - cy.log("type new values"); - cy.get(cesc("#\\/mi1") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}2y+1{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should("contain.text", "y"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2y+1", - ); - }); - - cy.get(cesc(`#\\/value`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2y+1"); - }); - - cy.reload(); - - cy.log("child overrides bindvalueto"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - bbb -

Original math: x

-

MathInput based on math and strings: y

-

Value mathinput:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "bbb"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("y"); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc(`#\\/value`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.log("type new values"); - cy.get(cesc("#\\/mi1") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}2z{enter}`, - { force: true }, - ); - - cy.get(cesc(`#\\/value`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2z"); - }); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2z", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.reload(); - - cy.log("normal downstream rules apply"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c -

Original math: 1+3x

-

MathInput based on math: $_math1

-

Copied mathinput:

-

Value of original mathinput:

-

Immediate value of original mathinput:

-

Value of copied mathinput:

-

Immediate value of copied mathinput:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "c"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3x+1", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3x+1", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - ["*", 3, "x"], - 1, - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "*", - 3, - "x", - ]); - }); - - cy.log("type new values"); - cy.get(cesc("#\\/mi1") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}xy{enter}`, - { force: true, delay: 100 }, - ); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "xy"); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "+", - ["*", "x", "y"], - -1, - ]); - }); - - cy.log("enter new values in reffed"); - cy.get(cesc(`#\\/mi2`) + ` textarea`).type( - `{end}{backspace}{backspace}qr{enter}`, - { force: true }, - ); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "qr"); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "+", - ["*", "q", "r"], - -1, - ]); - }); - }); - - it("values revert if bind to value that is not updatable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Original math: 1+2xz

-

MathInput based on math:

-

Copied mathinput:

-

Value of original mathinput:

-

Immediate value of original mathinput:

-

Value of copied mathinput:

-

Immediate value of copied mathinput:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2xz", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2xz", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - }); - - cy.log("type new values"); - cy.get(cesc("#\\/mi1") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}xy`, - { force: true, delay: 50 }, - ); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "xy", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "xy", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - }); - - cy.log("value revert when press enter"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{enter}`, { force: true }); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2xz", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2xz", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - }); - - cy.log("type new values in copy"); - cy.get(cesc(`#\\/mi2`) + ` textarea`).type( - `{ctrl+home}{shift+end}{backspace}qr`, - { force: true }, - ); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "qr", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "qr", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "qr", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qr"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "*", - "q", - "r", - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - }); - - cy.log("values revert when blur"); - cy.get(cesc(`#\\/mi2`) + ` textarea`).blur(); - - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "1+2xz", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "1+2xz", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2xz", - ); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "1+2xz", - ); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+2xz"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi1"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/mi2"].stateValues.immediateValue).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 1, - ["*", 2, "x", "z"], - ]); - }); - }); - - it("values revert if bind to fixed value", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Original math: x

-

MathInput based on math:

-

Copied mathinput:

-

Value of original mathinput:

-

Immediate value of original mathinput:

-

Value of copied mathinput:

-

Immediate value of copied mathinput:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eq("x"); - expect(stateVariables["/mi2"].stateValues.value).eq("x"); - expect(stateVariables["/mi1"].stateValues.immediateValue).eq("x"); - expect(stateVariables["/mi2"].stateValues.immediateValue).eq("x"); - expect(stateVariables["/_math1"].stateValues.value).eq("x"); - }); - - cy.log("type new values"); - // Note: had to add a larger delay in typing - // or MathJax consistently didn't correctly update the second immediate value. - // (At least when delay core's response by 1 second) - // Not sure what is going on here. - - cy.wait(1000); - cy.get(cesc("#\\/mi1") + " textarea").type(`{end}{backspace}y`, { - force: true, - delay: 100, - }); - - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "y", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "y", - ); - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "x"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "y", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "y", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("y"); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("y"); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eq("x"); - expect(stateVariables["/mi2"].stateValues.value).eq("x"); - expect(stateVariables["/mi1"].stateValues.immediateValue).eq("y"); - expect(stateVariables["/mi2"].stateValues.immediateValue).eq("y"); - expect(stateVariables["/_math1"].stateValues.value).eq("x"); - }); - - cy.log("value revert when press enter"); - cy.get(cesc("#\\/mi1") + " textarea").type(`{enter}`, { force: true }); - - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "x"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eq("x"); - expect(stateVariables["/mi2"].stateValues.value).eq("x"); - expect(stateVariables["/mi1"].stateValues.immediateValue).eq("x"); - expect(stateVariables["/mi2"].stateValues.immediateValue).eq("x"); - expect(stateVariables["/_math1"].stateValues.value).eq("x"); - }); - - cy.log("type new values in copy"); - cy.get(cesc(`#\\/mi2`) + ` textarea`).type(`{end}{backspace}z`, { - force: true, - }); - - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "z", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "z", - ); - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "x"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "z", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "z", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("z"); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("z"); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eq("x"); - expect(stateVariables["/mi2"].stateValues.value).eq("x"); - expect(stateVariables["/mi1"].stateValues.immediateValue).eq("z"); - expect(stateVariables["/mi2"].stateValues.immediateValue).eq("z"); - expect(stateVariables["/_math1"].stateValues.value).eq("x"); - }); - - cy.log("values revert when blur"); - cy.get(cesc(`#\\/mi2`) + ` textarea`).blur(); - - cy.get(cesc(`#\\/immediate1`) + ` .mjx-mrow`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/immediate2`) + ` .mjx-mrow`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/_math1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/value1`) + ` .mjx-mrow`).should("contain.text", "x"); - cy.get(cesc(`#\\/value2`) + ` .mjx-mrow`).should("contain.text", "x"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "contain.text", - "x", - ); - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc(`#\\/value1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/value2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc(`#\\/immediate2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eq("x"); - expect(stateVariables["/mi2"].stateValues.value).eq("x"); - expect(stateVariables["/mi1"].stateValues.immediateValue).eq("x"); - expect(stateVariables["/mi2"].stateValues.immediateValue).eq("x"); - expect(stateVariables["/_math1"].stateValues.value).eq("x"); - }); - }); - - it("mathinput based on value of mathinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original mathinput:

-

mathinput based on mathinput:

-

Immediate value of original:

-

Value of original:

-

Immediate value of second:

-

Value of second:

- `, - }, - "*", - ); - }); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+1", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+1", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 1]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 1]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - }); - - cy.log("type 2 first mathinput"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type(`{end}2`, { - force: true, - }); - - cy.get(cesc("#\\/originalimmediate") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "x+1", - ); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+1", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 1]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type(`{enter}`, { - force: true, - }); - - cy.get(cesc("#\\/originalvalue") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/originalimmediate") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/secondimmediate") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/secondvalue") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - }); - - cy.log("type 3 in second mathinput"); - cy.get(cesc("#\\/_mathinput2") + " textarea").type(`{end}3`, { - force: true, - }); - - cy.get(cesc("#\\/secondimmediate") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "x+123", - ); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+123", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 123]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - }); - - cy.log("leave second mathinput"); - cy.get(cesc("#\\/_mathinput2") + " textarea").blur(); - - cy.get(cesc("#\\/originalvalue") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - cy.get(cesc("#\\/secondvalue") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - cy.get(cesc("#\\/originalimmediate") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - cy.get(cesc("#\\/secondimmediate") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+123", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "x+123", - ); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+123", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+123", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 123]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 123, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 123]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 123, - ]); - }); - }); - - it("mathinput based on immediate value of mathinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original mathinput:

-

mathinput based on mathinput:

-

Immediate value of original:

-

Value of original:

-

Immediate value of second:

-

Value of second:

- `, - }, - "*", - ); - }); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+1", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+1", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 1]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 1]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - }); - - cy.log("type 2 first mathinput"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type(`{end}2`, { - force: true, - }); - - cy.get(cesc("#\\/originalimmediate") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/secondimmediate") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/secondvalue") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/originalvalue") + " .mjx-mrow").should( - "contain.text", - "x+1", - ); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+1"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 1, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type(`{enter}`, { - force: true, - }); - - cy.get(cesc("#\\/originalvalue") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/secondvalue") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/originalimmediate") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/secondimmediate") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - }); - - cy.log("type 3 in second mathinput"); - cy.get(cesc("#\\/_mathinput2") + " textarea").type(`{end}3`, { - force: true, - }); - - cy.get(cesc("#\\/secondimmediate") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - cy.get(cesc("#\\/originalimmediate") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/originalvalue") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - cy.get(cesc("#\\/secondvalue") + " .mjx-mrow").should( - "contain.text", - "x+12", - ); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+12", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "x+123", - ); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+12", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+123", - ); - }); - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+12"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 12]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 123]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 12, - ]); - }); - - cy.log("leave second mathinput"); - cy.get(cesc("#\\/_mathinput2") + " textarea").blur(); - - cy.get(cesc("#\\/originalimmediate") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - cy.get(cesc("#\\/originalvalue") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - cy.get(cesc("#\\/secondvalue") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - cy.get(cesc("#\\/secondimmediate") + " .mjx-mrow").should( - "contain.text", - "x+123", - ); - - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`).should( - "contain.text", - "x+123", - ); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`).should( - "contain.text", - "x+123", - ); - cy.get(cesc(`#\\/_mathinput1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+123", - ); - }); - cy.get(cesc(`#\\/_mathinput2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x+123", - ); - }); - - cy.get(cesc("#\\/originalimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - cy.get(cesc("#\\/originalvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - cy.get(cesc("#\\/secondimmediate")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - cy.get(cesc("#\\/secondvalue")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+123"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_mathinput1"].stateValues.immediateValue, - ).eqls(["+", "x", 123]); - expect(stateVariables["/_mathinput1"].stateValues.value).eqls([ - "+", - "x", - 123, - ]); - expect( - stateVariables["/_mathinput2"].stateValues.immediateValue, - ).eqls(["+", "x", 123]); - expect(stateVariables["/_mathinput2"].stateValues.value).eqls([ - "+", - "x", - 123, - ]); - }); - }); - - it("accurately reduce vector length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Enter vector - - - `, - }, - "*", - ); - }); - - // verify fixed bug where didn't reduce size of a vector - - cy.get(cesc("#\\/_text1")).should("have.text", "Enter vector"); - - cy.wait(1000); - - cy.get(cesc("#\\/a") + " textarea").type("(1,2,3){enter}", { - force: true, - }); - cy.get(cesc("#\\/b") + " .mjx-mrow").should("contain.text", "(1,2,3)"); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,3)"); - }); - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}(2,3){enter}", - { force: true }, - ); - cy.get(cesc("#\\/b") + " .mjx-mrow").should("contain.text", "(2,3)"); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,3)"); - }); - }); - - it("function symbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f, g:

-

- -

h, q:

-

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/b2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - - cy.get(cesc("#\\/a") + " textarea").type("f(x){enter}", { - force: true, - }); - cy.get(cesc("#\\/b") + " textarea").type("f(x){enter}", { - force: true, - }); - - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "f(x)"); - cy.get(cesc("#\\/b2") + " .mjx-mrow").should("contain.text", "fx"); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)"); - }); - cy.get(cesc("#\\/b2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("fx"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "f", - "x", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "f", - "x", - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - "f", - "x", - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - "f", - "x", - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}g(f){enter}", - { force: true }, - ); - cy.get(cesc("#\\/b") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}g(f){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "g(f)"); - cy.get(cesc("#\\/b2") + " .mjx-mrow").should("contain.text", "gf"); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("g(f)"); - }); - cy.get(cesc("#\\/b2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("gf"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "g", - "f", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "g", - "f", - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - "g", - "f", - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - "g", - "f", - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(q){enter}", - { force: true }, - ); - cy.get(cesc("#\\/b") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(q){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "hq"); - cy.get(cesc("#\\/b2") + " .mjx-mrow").should("contain.text", "h(q)"); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hq"); - }); - cy.get(cesc("#\\/b2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(q)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - "h", - "q", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - "h", - "q", - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "apply", - "h", - "q", - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "apply", - "h", - "q", - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}q(z){enter}", - { force: true }, - ); - cy.get(cesc("#\\/b") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}q(z){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "qz"); - cy.get(cesc("#\\/b2") + " .mjx-mrow").should("contain.text", "q(z)"); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("qz"); - }); - cy.get(cesc("#\\/b2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("q(z)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - "q", - "z", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - "q", - "z", - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "apply", - "q", - "z", - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "apply", - "q", - "z", - ]); - }); - }); - - it("display digits", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2:

-

a3:

-

a4:

-

a5:

- -

b: 10e^(3y)

-

b2:

-

b3:

-

b4:

-

b5:

-

b6:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(2x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "10e3y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{leftArrow}{leftArrow}{backspace}345.15389319{ctrl+end}", - { force: true }, - ); - - cy.get(cesc("#\\/a5") + " .mjx-mrow").should( - "contain.text", - "sin(345.15389319x)", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(345.15389319x)", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "sin(2x)"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(345.15389319x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15x)"); - }); - cy.get(cesc("#\\/a4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/a5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15389319x)"); - }); - - cy.get(cesc("#\\/b2") + " textarea").type( - "{ctrl+home}{rightArrow}{rightArrow}{backspace}{backspace}2.047529344518{ctrl+end}{leftArrow}{leftArrow}{backspace}0.0000073013048309{ctrl+end}", - { force: true }, - ); - - cy.get(cesc("#\\/b6") + " .mjx-mrow").should( - "contain.text", - "2.047529344518e0.0000073013048309y", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(345.15x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15x)"); - }); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should("contain.text", "10e3y"); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "2.047529344518e0.0000073013048309y", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should("contain.text", "10e3y"); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should( - "contain.text", - "2.05e0.0000073y", - ); - - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2.047529344518e0.0000073013048309y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.05e0.0000073y"); - }); - - cy.get(cesc("#\\/b2") + " textarea").blur(); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "2.047529345e0.000007301304831y", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "2.05e0.0000073y", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should( - "contain.text", - "2.05e0.0000073y", - ); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should( - "contain.text", - "2.05e0.0000073y", - ); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.047529345e0.000007301304831y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2.05e0.0000073y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.05e0.0000073y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.05e0.0000073y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - console.log(stateVariables["/a3"].stateValues.value); - console.log(["apply", "sin", ["*", 345.15389319, "x"]]); - - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 2.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 2.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 2.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{leftArrow}{leftArrow}{backspace}4{ctrl+end}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(345.14x)", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(345.14x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.14x)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").blur(); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(345.14x)", - ); - }); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.14x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.14x)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - }); - - cy.get(cesc("#\\/b2") + " textarea").type( - "{ctrl+home}{rightArrow}{backspace}6{ctrl+home}", - { force: true }, - ); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "2.047529345e0.000007301304831y", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "6.05e0.0000073y", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should( - "contain.text", - "2.05e0.0000073y", - ); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should( - "contain.text", - "6.05e0.0000073y", - ); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.047529345e0.000007301304831y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "6.05e0.0000073y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.05e0.0000073y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.05e0.0000073y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 2.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 2.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - }); - - cy.get(cesc("#\\/b2") + " textarea").blur(); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "6.05e0.0000073y", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "6.05e0.0000073y", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should( - "contain.text", - "6.05e0.0000073y", - ); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should( - "contain.text", - "6.05e0.0000073y", - ); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.05e0.0000073y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "6.05e0.0000073y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.05e0.0000073y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.05e0.0000073y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 6.05, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - }); - }); - - it("display decimals", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2:

-

a3:

- -

b: 10e^(3y)

-

b2:

-

b3:

-

b4:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(2x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "10e3y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{leftArrow}{leftArrow}{backspace}345.15389319{ctrl+end}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(345.15389319x)", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "sin(2x)"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(345.15389319x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15x)"); - }); - - cy.get(cesc("#\\/b2") + " textarea").type( - "{ctrl+home}{rightArrow}{rightArrow}{backspace}{backspace}2.047529344518{ctrl+end}{leftArrow}{leftArrow}{backspace}0.0000073013048309{ctrl+end}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(345.15x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15x)"); - }); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should("contain.text", "10e3y"); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "2.047529344518e0.0000073013048309y", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should("contain.text", "10e3y"); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should( - "contain.text", - "2.04752934e0.0000073y", - ); - - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2.047529344518e0.0000073013048309y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.04752934e0.0000073y"); - }); - - cy.get(cesc("#\\/b2") + " textarea").blur(); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "2.047529345e0.000007301304831y", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "2.04752934e0.0000073y", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should( - "contain.text", - "2.04752934e0.0000073y", - ); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should( - "contain.text", - "2.04752934e0.0000073y", - ); - - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.047529345e0.000007301304831y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2.04752934e0.0000073y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.04752934e0.0000073y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.04752934e0.0000073y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 2.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 2.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 2.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{leftArrow}{leftArrow}{backspace}4{ctrl+end}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(345.15x)", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(345.14x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.15x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.14x)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.15389319, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.15, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").blur(); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(345.14x)", - ); - }); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(345.14x)", - ); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.14x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(345.14x)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 345.14, "x"], - ]); - }); - - cy.get(cesc("#\\/b2") + " textarea").type( - "{ctrl+home}{rightArrow}{backspace}6{ctrl+home}", - { force: true }, - ); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "2.047529345e0.000007301304831y", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "6.04752934e0.0000073y", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should( - "contain.text", - "2.04752934e0.0000073y", - ); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should( - "contain.text", - "6.04752934e0.0000073y", - ); - - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.047529345e0.000007301304831y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "6.04752934e0.0000073y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.04752934e0.0000073y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.04752934e0.0000073y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 2.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 2.047529344518, - ["^", "e", ["*", 0.0000073013048309, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 2.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - }); - - cy.get(cesc("#\\/b2") + " textarea").blur(); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "6.04752934e0.0000073y", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "6.04752934e0.0000073y", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should( - "contain.text", - "6.04752934e0.0000073y", - ); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should( - "contain.text", - "6.04752934e0.0000073y", - ); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "6.04752934e0.0000073y", - ); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.04752934e0.0000073y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "6.04752934e0.0000073y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.04752934e0.0000073y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.04752934e0.0000073y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 6.04752934, - ["^", "e", ["*", 0.0000073, "y"]], - ]); - }); - }); - - it("display small as zero", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2:

-

a3:

-

a4:

-

a5:

- -

b: 10e^(3y)

-

b2:

-

b3:

-

b4:

- -

c:

-

c2:

-

c3:

- -

d: 10e^(3y)

-

d2:

-

d3:

-

d4:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(2x)", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "10e3y", - ); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/c") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "sin(2x)", - ); - }); - cy.get(cesc("#\\/c2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/c3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)"); - }); - cy.get(cesc("#\\/d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/d2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "10e3y", - ); - }); - cy.get(cesc("#\\/d3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - cy.get(cesc("#\\/d4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10e3y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/c"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/c"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/c2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/c2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/c3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/c3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 2, "x"], - ]); - expect(stateVariables["/d"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/d2"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/d2"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/d3"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/d3"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/d4"].stateValues.value).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - expect(stateVariables["/d4"].stateValues.valueForDisplay).eqls([ - "*", - 10, - ["^", "e", ["*", 3, "y"]], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+end}{leftArrow}{leftArrow}{backspace}0.000000000000000472946384739473{enter}", - { force: true }, - ); - cy.get(cesc("#\\/b2") + " textarea").type( - "{ctrl+home}{rightArrow}{rightArrow}{backspace}{backspace}0.0000000000000934720357236{ctrl+end}{leftArrow}{leftArrow}{backspace}0.0000000000000073013048309{enter}", - { force: true }, - ); - cy.get(cesc("#\\/c") + " textarea").type( - "{end}{leftArrow}{leftArrow}{backspace}0.000000000000000472946384739473{enter}", - { force: true }, - ); - cy.get(cesc("#\\/d2") + " textarea") - .type( - "{ctrl+home}{rightArrow}{rightArrow}{backspace}{backspace}0.0000000000000934720357236{ctrl+end}{leftArrow}{leftArrow}{backspace}0.0000000000000073013048309{enter}", - { force: true }, - ) - .blur(); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(4.7295", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(4.7295", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(4.7295", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/\u00B7/g, "\u22C5"), - ).equal("sin(4.7295β‹…10βˆ’16x)"); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(4.7295β‹…10βˆ’16x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(4.7295β‹…10βˆ’16x)"); - }); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "9.347203572", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "9.35", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should("contain.text", "9.35"); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should("contain.text", "9.35"); - - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "9.347203572β‹…10βˆ’14e7.301304831β‹…10βˆ’15y", - ); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/\u00B7/g, "\u22C5"), - ).equal("9.35β‹…10βˆ’14e7.3β‹…10βˆ’15y"); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9.35β‹…10βˆ’14e7.3β‹…10βˆ’15y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9.35β‹…10βˆ’14e7.3β‹…10βˆ’15y"); - }); - - cy.get(cesc("#\\/c") + " .mq-editable-field").should( - "contain.text", - "sin(0x)", - ); - cy.get(cesc("#\\/c2") + " .mjx-mrow").should("contain.text", "sin(0x)"); - cy.get(cesc("#\\/c3") + " .mjx-mrow").should("contain.text", "sin(0x)"); - cy.get(cesc("#\\/c") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/\u00B7/g, "\u22C5"), - ).equal("sin(0x)"); - }); - cy.get(cesc("#\\/c2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0x)"); - }); - cy.get(cesc("#\\/c3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0x)"); - }); - - cy.get(cesc("#\\/d") + " .mjx-mrow").should( - "contain.text", - "9.347203572", - ); - cy.get(cesc("#\\/d2") + " .mq-editable-field").should( - "contain.text", - "9.35", - ); - cy.get(cesc("#\\/d3") + " .mjx-mrow").should("contain.text", "9.35"); - cy.get(cesc("#\\/d4") + " .mjx-mrow").should("contain.text", "9.35"); - cy.get(cesc("#\\/d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "9.347203572β‹…10βˆ’14e7.301304831β‹…10βˆ’15y", - ); - }); - cy.get(cesc("#\\/d2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/\u00B7/g, "\u22C5"), - ).equal("9.35β‹…10βˆ’14e0y"); - }); - cy.get(cesc("#\\/d3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9.35β‹…10βˆ’14e0y"); - }); - cy.get(cesc("#\\/d4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9.35β‹…10βˆ’14e0y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 4.72946384739473e-16, "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 4.7295e-16, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 4.72946384739473e-16, "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 4.7295e-16, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 4.72946384739473e-16, "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 4.7295e-16, "x"], - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 9.34720357236e-14, - ["^", "e", ["*", 7.3013048309e-15, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 9.34720357236e-14, - ["^", "e", ["*", 7.3013048309e-15, "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 9.35e-14, - ["^", "e", ["*", 7.3e-15, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 9.34720357236e-14, - ["^", "e", ["*", 7.3013048309e-15, "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 9.35e-14, - ["^", "e", ["*", 7.3e-15, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 9.34720357236e-14, - ["^", "e", ["*", 7.3013048309e-15, "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 9.35e-14, - ["^", "e", ["*", 7.3e-15, "y"]], - ]); - expect(stateVariables["/c"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 4.72946384739473e-16, "x"], - ]); - expect(stateVariables["/c"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 0, "x"], - ]); - expect(stateVariables["/c2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 4.72946384739473e-16, "x"], - ]); - expect(stateVariables["/c2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 0, "x"], - ]); - expect(stateVariables["/c3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 4.72946384739473e-16, "x"], - ]); - expect(stateVariables["/c3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 0, "x"], - ]); - expect(stateVariables["/d"].stateValues.value).eqls([ - "*", - 9.34720357236e-14, - ["^", "e", ["*", 7.3013048309e-15, "y"]], - ]); - expect(stateVariables["/d2"].stateValues.value).eqls([ - "*", - 9.34720357236e-14, - ["^", "e", ["*", 7.3013048309e-15, "y"]], - ]); - expect(stateVariables["/d2"].stateValues.valueForDisplay).eqls([ - "*", - 9.35e-14, - ["^", "e", ["*", 0, "y"]], - ]); - expect(stateVariables["/d3"].stateValues.value).eqls([ - "*", - 9.34720357236e-14, - ["^", "e", ["*", 7.3013048309e-15, "y"]], - ]); - expect(stateVariables["/d3"].stateValues.valueForDisplay).eqls([ - "*", - 9.35e-14, - ["^", "e", ["*", 0, "y"]], - ]); - expect(stateVariables["/d4"].stateValues.value).eqls([ - "*", - 9.34720357236e-14, - ["^", "e", ["*", 7.3013048309e-15, "y"]], - ]); - expect(stateVariables["/d4"].stateValues.valueForDisplay).eqls([ - "*", - 9.35e-14, - ["^", "e", ["*", 0, "y"]], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{home}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/b2") + " textarea").type( - "{ctrl+home}{rightArrow}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/c") + " textarea").type( - "{end}{leftArrow}{leftArrow}{leftArrow}3{enter}", - { force: true, delay: 100 }, - ); - cy.get(cesc("#\\/d2") + " textarea") - .type("{ctrl+home}{rightArrow}{backspace}6{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "sin(5.7295", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "sin(5.7295", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "sin(5.7295", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/\u00B7/g, "\u22C5"), - ).equal("sin(5.7295β‹…10βˆ’16x)"); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(5.7295β‹…10βˆ’16x)"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(5.7295β‹…10βˆ’16x)"); - }); - - cy.get(cesc("#\\/b") + " .mjx-mrow").should("contain.text", "8.35"); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "8.35", - ); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should("contain.text", "8.35"); - cy.get(cesc("#\\/b4") + " .mjx-mrow").should("contain.text", "8.35"); - - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("8.35β‹…10βˆ’14e7.3β‹…10βˆ’15y"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/\u00B7/g, "\u22C5"), - ).equal("8.35β‹…10βˆ’14e7.3β‹…10βˆ’15y"); - }); - cy.get(cesc("#\\/b3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("8.35β‹…10βˆ’14e7.3β‹…10βˆ’15y"); - }); - cy.get(cesc("#\\/b4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("8.35β‹…10βˆ’14e7.3β‹…10βˆ’15y"); - }); - - cy.get(cesc("#\\/c") + " .mq-editable-field").should( - "contain.text", - "sin(30x)", - ); - cy.get(cesc("#\\/c2") + " .mjx-mrow").should( - "contain.text", - "sin(30x)", - ); - cy.get(cesc("#\\/c3") + " .mjx-mrow").should( - "contain.text", - "sin(30x)", - ); - cy.get(cesc("#\\/c") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/\u00B7/g, "\u22C5"), - ).equal("sin(30x)"); - }); - cy.get(cesc("#\\/c2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(30x)"); - }); - cy.get(cesc("#\\/c3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(30x)"); - }); - - cy.get(cesc("#\\/d") + " .mjx-mrow").should("contain.text", "6.35"); - cy.get(cesc("#\\/d2") + " .mq-editable-field").should( - "contain.text", - "6.35", - ); - cy.get(cesc("#\\/d3") + " .mjx-mrow").should("contain.text", "6.35"); - cy.get(cesc("#\\/d4") + " .mjx-mrow").should("contain.text", "6.35"); - cy.get(cesc("#\\/d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.35β‹…10βˆ’14e0y"); - }); - cy.get(cesc("#\\/d2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/\u00B7/g, "\u22C5"), - ).equal("6.35β‹…10βˆ’14e0y"); - }); - cy.get(cesc("#\\/d3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.35β‹…10βˆ’14e0y"); - }); - cy.get(cesc("#\\/d4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6.35β‹…10βˆ’14e0y"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 5.7295, ["^", 10, -16], "x"], - ]); - expect(stateVariables["/a"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 5.7295, ["^", 10, -16], "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 5.7295, ["^", 10, -16], "x"], - ]); - expect(stateVariables["/a2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 5.7295, ["^", 10, -16], "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 5.7295, ["^", 10, -16], "x"], - ]); - expect(stateVariables["/a3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 5.7295, ["^", 10, -16], "x"], - ]); - expect(stateVariables["/b"].stateValues.value).eqls([ - "*", - 8.35, - ["^", 10, -14], - ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], - ]); - expect(stateVariables["/b2"].stateValues.value).eqls([ - "*", - 8.35, - ["^", 10, -14], - ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], - ]); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eqls([ - "*", - 8.35, - ["^", 10, -14], - ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], - ]); - expect(stateVariables["/b3"].stateValues.value).eqls([ - "*", - 8.35, - ["^", 10, -14], - ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], - ]); - expect(stateVariables["/b3"].stateValues.valueForDisplay).eqls([ - "*", - 8.35, - ["^", 10, -14], - ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], - ]); - expect(stateVariables["/b4"].stateValues.value).eqls([ - "*", - 8.35, - ["^", 10, -14], - ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], - ]); - expect(stateVariables["/b4"].stateValues.valueForDisplay).eqls([ - "*", - 8.35, - ["^", 10, -14], - ["^", "e", ["*", 7.3, ["^", 10, -15], "y"]], - ]); - expect(stateVariables["/c"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 30, "x"], - ]); - expect(stateVariables["/c"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 30, "x"], - ]); - expect(stateVariables["/c2"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 30, "x"], - ]); - expect(stateVariables["/c2"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 30, "x"], - ]); - expect(stateVariables["/c3"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 30, "x"], - ]); - expect(stateVariables["/c3"].stateValues.valueForDisplay).eqls([ - "apply", - "sin", - ["*", 30, "x"], - ]); - expect(stateVariables["/d"].stateValues.value).eqls([ - "*", - 6.35, - ["^", 10, -14], - ["^", "e", ["*", 0, "y"]], - ]); - expect(stateVariables["/d2"].stateValues.value).eqls([ - "*", - 6.35, - ["^", 10, -14], - ["^", "e", ["*", 0, "y"]], - ]); - expect(stateVariables["/d2"].stateValues.valueForDisplay).eqls([ - "*", - 6.35, - ["^", 10, -14], - ["^", "e", ["*", 0, "y"]], - ]); - expect(stateVariables["/d3"].stateValues.value).eqls([ - "*", - 6.35, - ["^", 10, -14], - ["^", "e", ["*", 0, "y"]], - ]); - expect(stateVariables["/d3"].stateValues.valueForDisplay).eqls([ - "*", - 6.35, - ["^", 10, -14], - ["^", "e", ["*", 0, "y"]], - ]); - expect(stateVariables["/d4"].stateValues.value).eqls([ - "*", - 6.35, - ["^", 10, -14], - ["^", "e", ["*", 0, "y"]], - ]); - expect(stateVariables["/d4"].stateValues.valueForDisplay).eqls([ - "*", - 6.35, - ["^", 10, -14], - ["^", "e", ["*", 0, "y"]], - ]); - }); - }); - - it("propagate larger default display digits", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2:

-

a3:

-

a4:

-

a5:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "123.4567891", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("123.4567891"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("123.4567891"); - }); - cy.get(cesc("#\\/a4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("123.46"); - }); - cy.get(cesc("#\\/a5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("123.46"); - }); - - cy.get(cesc("#\\/a") + " textarea") - .type( - "{ctrl+home}{ctrl+shift+end}{backspace}98765.4321876{ctrl+end}", - { - force: true, - }, - ) - .blur(); - - cy.get(cesc("#\\/a4") + " .mjx-mrow").should("contain.text", "98765"); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "98765.43219", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("98765.43219"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("98765.43219"); - }); - cy.get(cesc("#\\/a4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("98765.43"); - }); - cy.get(cesc("#\\/a5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("98765.43"); - }); - }); - - it("propagate false default display small as zero", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2:

-

a3:

-

a4:

-

a5:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "123.4567891", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("123.4567891"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("123.4567891"); - }); - cy.get(cesc("#\\/a4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("123.4567891"); - }); - cy.get(cesc("#\\/a5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("123.4567891"); - }); - - cy.get(cesc("#\\/a") + " textarea") - .type( - "{ctrl+home}{ctrl+shift+end}{backspace}0.00000000000000004736286523434185{ctrl+end}", - { - force: true, - }, - ) - .blur(); - - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "4.736286523", - ); - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "4.736286523Β·10βˆ’17", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4.736286523β‹…10βˆ’17"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4.736286523β‹…10βˆ’17"); - }); - cy.get(cesc("#\\/a4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/a5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - }); - - it("display digits, change from downstream", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

- -

b: 5

-

b2:

- - - ($a, $b2) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("3"); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq(3); - expect(stateVariables["/a"].stateValues.valueForDisplay).eq(3); - expect(stateVariables["/p"].stateValues.xs[0]).eq(3); - expect(stateVariables["/b"].stateValues.value).eq(5); - expect(stateVariables["/b2"].stateValues.value).eq(5); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eq(5); - expect(stateVariables["/p"].stateValues.xs[1]).eq(5); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{backspace}2.4295639461593{enter}", - { force: true }, - ); - cy.get(cesc("#\\/b2") + " textarea") - .type("{end}{backspace}9.3935596792746{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "2.4296", - ); - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "9.393559679", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "9.39", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2.4296", - ); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9.393559679"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "9.39", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq(2.4295639461593); - expect(stateVariables["/a"].stateValues.valueForDisplay).eq(2.4296); - expect(stateVariables["/p"].stateValues.xs[0]).eq(2.4295639461593); - expect(stateVariables["/b"].stateValues.value).eq(9.3935596792746); - expect(stateVariables["/b2"].stateValues.value).eq(9.3935596792746); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eq(9.39); - expect(stateVariables["/p"].stateValues.xs[1]).eq(9.3935596792746); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/p", - args: { x: 7.936497798143, y: 2.142218345836 }, - }); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "7.9365", - ); - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "2.142218346", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "2.14", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "7.9365", - ); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.142218346"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2.14", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq( - 7.936497798143, - ); - expect(stateVariables["/a"].stateValues.valueForDisplay).eq( - 7.9365, - ); - expect(stateVariables["/p"].stateValues.xs[0]).eq( - 7.936497798143, - ); - expect(stateVariables["/b"].stateValues.value).eq( - 2.142218345836, - ); - expect(stateVariables["/b2"].stateValues.value).eq( - 2.142218345836, - ); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eq( - 2.14, - ); - expect(stateVariables["/p"].stateValues.xs[1]).eq( - 2.142218345836, - ); - }); - }); - }); - - it("display decimals, change from downstream", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

- -

b: 5

-

b2:

- - - ($a, $b2) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("3"); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq(3); - expect(stateVariables["/a"].stateValues.valueForDisplay).eq(3); - expect(stateVariables["/p"].stateValues.xs[0]).eq(3); - expect(stateVariables["/b"].stateValues.value).eq(5); - expect(stateVariables["/b2"].stateValues.value).eq(5); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eq(5); - expect(stateVariables["/p"].stateValues.xs[1]).eq(5); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{backspace}2.4295639461593{enter}", - { force: true }, - ); - cy.get(cesc("#\\/b2") + " textarea") - .type("{end}{backspace}9.3935596792746{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "2.4296", - ); - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "9.393559679", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "9.39", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2.4296", - ); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9.393559679"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "9.39", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq(2.4295639461593); - expect(stateVariables["/a"].stateValues.valueForDisplay).eq(2.4296); - expect(stateVariables["/p"].stateValues.xs[0]).eq(2.4295639461593); - expect(stateVariables["/b"].stateValues.value).eq(9.3935596792746); - expect(stateVariables["/b2"].stateValues.value).eq(9.3935596792746); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eq(9.39); - expect(stateVariables["/p"].stateValues.xs[1]).eq(9.3935596792746); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/p", - args: { x: 7.936497798143, y: 2.142218345836 }, - }); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "7.9365", - ); - cy.get(cesc("#\\/b") + " .mjx-mrow").should( - "contain.text", - "2.142218346", - ); - cy.get(cesc("#\\/b2") + " .mq-editable-field").should( - "contain.text", - "2.14", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "7.9365", - ); - }); - cy.get(cesc("#\\/b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2.142218346"); - }); - cy.get(cesc("#\\/b2") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "2.14", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq( - 7.936497798143, - ); - expect(stateVariables["/a"].stateValues.valueForDisplay).eq( - 7.9365, - ); - expect(stateVariables["/p"].stateValues.xs[0]).eq( - 7.936497798143, - ); - expect(stateVariables["/b"].stateValues.value).eq( - 2.142218345836, - ); - expect(stateVariables["/b2"].stateValues.value).eq( - 2.142218345836, - ); - expect(stateVariables["/b2"].stateValues.valueForDisplay).eq( - 2.14, - ); - expect(stateVariables["/p"].stateValues.xs[1]).eq( - 2.142218345836, - ); - }); - }); - }); - - it("natural input to sqrt", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2: $a.value{assignNames="a2"}

-

a3:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "_"); - - cy.get(cesc("#\\/a") + " textarea").type("sqrt4{enter}", { - force: true, - }); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "√4", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "√4"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "√4", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√4"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - }); - - it("substitute unicode", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2: $a.value{assignNames="a2"}

-

a3:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "οΌΏ"); - - cy.log(`unicode Ξ± U+03B1`); - cy.get(cesc("#\\/a") + " textarea").type("Ξ±{enter}", { force: true }); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "Ξ±", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "Ξ±"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "Ξ±"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("Ξ±"); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Ξ±"); - }); - cy.get(cesc("#\\/a3")) - .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["/a"].stateValues.value).eqls("alpha"); - expect(stateVariables["/a2"].stateValues.value).eqls("alpha"); - expect(stateVariables["/a3"].stateValues.value).eqls("alpha"); - }); - - cy.log(`latex \\alpha\\beta`); - // Note: first {enter} changes \beta to Ξ² and second {enter} is detected as an Enter - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{backspace}\\alpha\\beta{enter}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "Ξ±Ξ²", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "Ξ±Ξ²"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "Ξ±Ξ²"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "Ξ±Ξ²", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("Ξ±Ξ²"); - }); - cy.get(cesc("#\\/a3")) - .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["/a"].stateValues.value).eqls([ - "*", - "alpha", - "beta", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - "alpha", - "beta", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - "alpha", - "beta", - ]); - }); - - cy.log(`unicode βˆ’ U+2212 is subtraction`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{backspace}{backspace}y\u2212z{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "yβˆ’z", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "yβˆ’z"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "yβˆ’z"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "yβˆ’z", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yβˆ’z"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yβˆ’z"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "+", - "y", - ["-", "z"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "+", - "y", - ["-", "z"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "+", - "y", - ["-", "z"], - ]); - }); - - cy.log(`normal minus`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}a-b{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "aβˆ’b", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "aβˆ’b"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "aβˆ’b"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "aβˆ’b", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("aβˆ’b"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("aβˆ’b"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "+", - "a", - ["-", "b"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "+", - "a", - ["-", "b"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "+", - "a", - ["-", "b"], - ]); - }); - - cy.log(`unicode β‹… U+22C5 is multiplication`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}y\u22C5z{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "yβ‹…z", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "yz"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "yz"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "yβ‹…z", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yz"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yz"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - "y", - "z", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - "y", - "z", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - "y", - "z", - ]); - }); - - cy.log(`normal *`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}a*b{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "a\u00B7b", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "ab"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "ab"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "a\u00B7b", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ab"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ab"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - "a", - "b", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - "a", - "b", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - "a", - "b", - ]); - }); - - cy.log(`unicode Β· U+00B7 becomes multiplication`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}y\u00B7z{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "y\u00B7z", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "yz"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "yz"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "y\u00B7z", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yz"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("yz"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - "y", - "z", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - "y", - "z", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - "y", - "z", - ]); - }); - - cy.log(`unicode Γ— U+00D7 becomes multiplication`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}u\u00D7v{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "u\u00D7v", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "uv"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "uv"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "u\u00D7v", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - "u", - "v", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - "u", - "v", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - "u", - "v", - ]); - }); - - cy.log(`unicode βˆͺ U+222A becomes union`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}A\u222AB{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "A\u222AB", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "A\u222AB", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "A\u222AB", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "A\u222AB", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A\u222AB"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A\u222AB"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - }); - - cy.log(`unicode ∩ U+2229 becomes intersect`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}A\u2229B{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "A\u2229B", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should( - "contain.text", - "A\u2229B", - ); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "A\u2229B", - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "A\u2229B", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A\u2229B"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A\u2229B"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "intersect", - "A", - "B", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "intersect", - "A", - "B", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "intersect", - "A", - "B", - ]); - }); - - cy.log(`unicode ∞ U+221E becomes infinity`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}\u221E{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "\u221E", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "\u221E"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "\u221E"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "\u221E", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\u221E"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\u221E"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq(Infinity); - expect(stateVariables["/a2"].stateValues.value).eq(Infinity); - expect(stateVariables["/a3"].stateValues.value).eq(Infinity); - }); - - cy.log(`unicode Β΅ U+00B5 becomes mu`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}\u00B5{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "\u00B5", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "\u03BC"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "\u03BC"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "\u00B5", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\u03BC"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\u03BC"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq("mu"); - expect(stateVariables["/a2"].stateValues.value).eq("mu"); - expect(stateVariables["/a3"].stateValues.value).eq("mu"); - }); - - cy.log(`unicode ΞΌ U+03BC becomes mu`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}\u03BC{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "\u03BC", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "\u03BC"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "\u03BC"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "\u03BC", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\u03BC"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\u03BC"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq("mu"); - expect(stateVariables["/a2"].stateValues.value).eq("mu"); - expect(stateVariables["/a3"].stateValues.value).eq("mu"); - }); - - cy.log(`unicode β€² U+2032 becomes apostrophe`); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}f\u2032{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "f\u2032", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "f\u2032"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "f\u2032"); - - cy.get(cesc("#\\/a") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "f\u2032", - ); - }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f\u2032"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f\u2032"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls(["prime", "f"]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "prime", - "f", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "prime", - "f", - ]); - }); - }); - - it("exponent with numbers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2: $a.value{assignNames="a2"}

-

a3: $a

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "οΌΏ"); - - cy.get(cesc("#\\/a") + " textarea").type("3^2{rightArrow}5{enter}", { - force: true, - }); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "325", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "32β‹…5"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "45"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["^", 3, 2], - 5, - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["^", 3, 2], - 5, - ]); - expect(stateVariables["/a3"].stateValues.value).eqls(45); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3^25{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "325", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "325"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should( - "contain.text", - "847288609443", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls(["^", 3, 25]); - expect(stateVariables["/a2"].stateValues.value).eqls(["^", 3, 25]); - expect(stateVariables["/a3"].stateValues.value).eqls(847288609443); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3^2x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "32x", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "32x"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "32x"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "^", - 3, - ["*", 2, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "^", - 3, - ["*", 2, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "^", - 3, - ["*", 2, "x"], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3^2{rightarrow}x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "32x", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "32x"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "9x"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["^", 3, 2], - "x", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["^", 3, 2], - "x", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls(["*", 9, "x"]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3^x2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "3x2", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "3x2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "3x2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls(["^", 3, "x2"]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "^", - 3, - "x2", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "^", - 3, - "x2", - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3^x{rightarrow}2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "3x2", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "3xβ‹…2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2β‹…3x"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["^", 3, "x"], - 2, - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["^", 3, "x"], - 2, - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - 2, - ["^", 3, "x"], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}f^3{rightarrow}2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "f32", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "f3β‹…2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2f3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["^", "f", 3], - 2, - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["^", "f", 3], - 2, - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - 2, - ["^", "f", 3], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}x^3{rightarrow}2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "x32", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "x3β‹…2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2x3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["^", "x", 3], - 2, - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["^", "x", 3], - 2, - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - 2, - ["^", "x", 3], - ]); - }); - }); - - it("subscript with numbers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a:

-

a2: $a.value{assignNames="a2"}

-

a3: $a

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "οΌΏ"); - - cy.get(cesc("#\\/a") + " textarea").type("3_2{rightArrow}5{enter}", { - force: true, - }); - - cy.get(cesc(`#\\/a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "325", - ); - }); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "32β‹…5"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "5β‹…32"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["_", 3, 2], - 5, - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["_", 3, 2], - 5, - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - 5, - ["_", 3, 2], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3_25{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "325", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "325"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "325"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls(["_", 3, 25]); - expect(stateVariables["/a2"].stateValues.value).eqls(["_", 3, 25]); - expect(stateVariables["/a3"].stateValues.value).eqls(["_", 3, 25]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3_2x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "32x", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "32x"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "32x"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "_", - 3, - ["*", 2, "x"], - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "_", - 3, - ["*", 2, "x"], - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "_", - 3, - ["*", 2, "x"], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3_2{rightarrow}x{enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "32x", - ); - }); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "32x"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "xβ‹…32"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["_", 3, 2], - "x", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["_", 3, 2], - "x", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - "x", - ["_", 3, 2], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3_x2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/a") + " .mq-editable-field").should( - "contain.text", - "3x2", - ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "3x2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "3x2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls(["_", 3, "x2"]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "_", - 3, - "x2", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "_", - 3, - "x2", - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}3_x{rightarrow}2{enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3x2", - ); - }); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "3xβ‹…2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2β‹…3x"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["_", 3, "x"], - 2, - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["_", 3, "x"], - 2, - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - 2, - ["_", 3, "x"], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}f_3{rightarrow}2{enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "f32", - ); - }); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "f3β‹…2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2f3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["_", "f", 3], - 2, - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["_", "f", 3], - 2, - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - 2, - ["_", "f", 3], - ]); - }); - - cy.get(cesc("#\\/a") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}x_3{rightarrow}2{enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x32", - ); - }); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "x3β‹…2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2x3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eqls([ - "*", - ["_", "x", 3], - 2, - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "*", - ["_", "x", 3], - 2, - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "*", - 2, - ["_", "x", 3], - ]); - }); - }); - - it("rawValue is updated", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/Ax")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/mi2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("1"); - expect(stateVariables["/mi"].stateValues.immediateValue).eq(1); - expect(stateVariables["/mi"].stateValues.value).eq(1); - expect(stateVariables["/A"].stateValues.xs.map((x) => x)).eqls([ - 1, 2, - ]); - expect(stateVariables["/B"].stateValues.xs.map((x) => x)).eqls([ - 1, 3, - ]); - }); - - cy.get(cesc("#\\/mi") + " textarea").type( - "{end}{backspace}-7.4{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should("contain.text", "βˆ’7"); - cy.get(cesc("#\\/mi2") + " .mjx-mrow").should("contain.text", "βˆ’7"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "contain.text", - "βˆ’7", - ); - - cy.get(cesc("#\\/Ax")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("βˆ’7"); - }); - cy.get(cesc("#\\/mi2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("βˆ’7"); - }); - cy.get(cesc("#\\/mi") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "βˆ’7", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("-7"); - expect(stateVariables["/mi"].stateValues.immediateValue).eq(-7); - expect(stateVariables["/mi"].stateValues.value).eq(-7); - expect(stateVariables["/A"].stateValues.xs.map((x) => x)).eqls([ - -7, 2, - ]); - expect(stateVariables["/B"].stateValues.xs.map((x) => x)).eqls([ - -7, 3, - ]); - }); - - cy.log("move point A"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: 3.9, y: -8.4 }, - }); - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should("contain.text", "4"); - cy.get(cesc("#\\/mi2") + " .mjx-mrow").should("contain.text", "4"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "contain.text", - "4", - ); - - cy.get(cesc("#\\/Ax")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/mi2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("4"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("4"); - expect(stateVariables["/mi"].stateValues.immediateValue).eq(4); - expect(stateVariables["/mi"].stateValues.value).eq(4); - expect(stateVariables["/A"].stateValues.xs.map((x) => x)).eqls([ - 4, -8, - ]); - expect(stateVariables["/B"].stateValues.xs.map((x) => x)).eqls([ - 4, 3, - ]); - }); - - cy.log("move point B"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: 5.1, y: 1.3 }, - }); - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should("contain.text", "5"); - cy.get(cesc("#\\/mi2") + " .mjx-mrow").should("contain.text", "5"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "contain.text", - "5", - ); - - cy.get(cesc("#\\/Ax")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/mi2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("5"); - expect(stateVariables["/mi"].stateValues.immediateValue).eq(5); - expect(stateVariables["/mi"].stateValues.value).eq(5); - expect(stateVariables["/A"].stateValues.xs.map((x) => x)).eqls([ - 5, -8, - ]); - expect(stateVariables["/B"].stateValues.xs.map((x) => x)).eqls([ - 5, 1.3, - ]); - }); - }); - - it("chain update off mathinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/mi") + " textarea").type("y", { force: true }); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/mi") + " textarea").type("{backspace}x", { - force: true, - }); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("have.text", "x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/mi") + " textarea").blur(); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("have.text", "2x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}y", { - force: true, - }); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("have.text", "2x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - - cy.get(cesc("#\\/mi") + " textarea").type("+x", { force: true }); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("have.text", "2x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("have.text", "3x+y"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+y"); - }); - }); - - it("split symbols in mathinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

No split:

-

Split:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mns") + " .mjx-mrow").should("contain.text", "οΌΏ"); - cy.get(cesc("#\\/mins") + " textarea").type("xy{enter}", { - force: true, - }); - cy.get(cesc("#\\/mis") + " textarea").type("xy{enter}", { - force: true, - }); - cy.get(cesc("#\\/mns") + " .mjx-mrow").should("contain.text", "xy"); - cy.get(cesc("#\\/ms") + " .mjx-mrow").should("contain.text", "xy"); - cy.get(cesc("#\\/mns")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/ms")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mins"].stateValues.value).eqls("xy"); - expect(stateVariables["/mis"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/mns"].stateValues.value).eqls("xy"); - expect(stateVariables["/ms"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - }); - - cy.get(cesc("#\\/mins") + " textarea").type("{end}0{enter}", { - force: true, - }); - cy.get(cesc("#\\/mis") + " textarea").type("{end}0{enter}", { - force: true, - }); - cy.get(cesc("#\\/mns") + " .mjx-mrow").should("contain.text", "xy0"); - cy.get(cesc("#\\/ms") + " .mjx-mrow").should("contain.text", "xy0"); - cy.get(cesc("#\\/mns")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy0"); - }); - cy.get(cesc("#\\/ms")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mins"].stateValues.value).eqls("xy0"); - expect(stateVariables["/mis"].stateValues.value).eqls("xy0"); - expect(stateVariables["/mns"].stateValues.value).eqls("xy0"); - expect(stateVariables["/ms"].stateValues.value).eqls("xy0"); - }); - - cy.get(cesc("#\\/mins") + " textarea").type( - "{end}{backspace}_uv{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mis") + " textarea").type( - "{end}{backspace}_uv{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mns") + " .mjx-mrow").should("contain.text", "xyuv"); - cy.get(cesc("#\\/ms") + " .mjx-mrow").should("contain.text", "xyuv"); - cy.get(cesc("#\\/mns")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc("#\\/ms")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mins"].stateValues.value).eqls([ - "_", - "xy", - "uv", - ]); - expect(stateVariables["/mis"].stateValues.value).eqls([ - "*", - "x", - ["_", "y", ["*", "u", "v"]], - ]); - expect(stateVariables["/mns"].stateValues.value).eqls([ - "_", - "xy", - "uv", - ]); - expect(stateVariables["/ms"].stateValues.value).eqls([ - "*", - "x", - ["_", "y", ["*", "u", "v"]], - ]); - }); - }); - - it("normalize begin/end ldots in mathinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("use periods, no commas"); - // for some reason, need a significant delay in between keystrokes - // or MathJax doesn't render immediate value correctly. - cy.get(cesc("#\\/mi") + " textarea").type("...x,y,z...{enter}", { - force: true, - delay: 100, - }); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "…,x,y,z,…", - ); - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("…,x,y,z,…"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "list", - ["ldots"], - "x", - "y", - "z", - ["ldots"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "list", - ["ldots"], - "x", - "y", - "z", - ["ldots"], - ]); - }); - - cy.log("add spaces in between some periods"); - - cy.get(cesc("#\\/mi") + " textarea").type( - "{home} {rightarrow} {rightarrow} {end} {leftarrow}{leftarrow} {leftarrow}{leftarrow}{leftarrow}{backspace}a{end}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "…,x,y,a,…", - ); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("…,x,y,a,…"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "list", - ["ldots"], - "x", - "y", - "a", - ["ldots"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "list", - ["ldots"], - "x", - "y", - "a", - ["ldots"], - ]); - }); - - cy.log("add commas after first set of periods"); - - cy.get(cesc("#\\/mi") + " textarea").type( - "{home}{rightarrow}{rightarrow}{rightarrow}{rightarrow}{rightarrow}{rightarrow},{rightarrow}{backspace}b{end}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "…,b,y,a,…", - ); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("…,b,y,a,…"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "list", - ["ldots"], - "b", - "y", - "a", - ["ldots"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "list", - ["ldots"], - "b", - "y", - "a", - ["ldots"], - ]); - }); - - cy.log("add commas before second set of periods"); - - cy.get(cesc("#\\/mi") + " textarea").type( - "{end}{leftarrow}{leftarrow}{leftarrow}{leftarrow}{leftarrow},{leftarrow}{backspace}c{end}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "…,b,y,c,…", - ); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("…,b,y,c,…"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "list", - ["ldots"], - "b", - "y", - "c", - ["ldots"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "list", - ["ldots"], - "b", - "y", - "c", - ["ldots"], - ]); - }); - - cy.log("change second set of periods to ldots"); - - cy.get(cesc("#\\/mi") + " textarea").type( - "{end}{backspace}{backspace}{backspace}{backspace}{backspace}{leftarrow}{backspace}d{rightarrow}\\ldots {enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "…,b,y,d,…", - ); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("…,b,y,d,…"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "list", - ["ldots"], - "b", - "y", - "d", - ["ldots"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "list", - ["ldots"], - "b", - "y", - "d", - ["ldots"], - ]); - }); - - cy.log("change first set of periods to ldots"); - - cy.get(cesc("#\\/mi") + " textarea").type( - "{home}{rightarrow}{rightarrow}{rightarrow}{rightarrow}{rightarrow}{rightarrow}{backspace}{backspace}{backspace}{backspace}{backspace}\\ldots {rightarrow}{rightarrow}{backspace}e{end}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "…,e,y,d,…", - ); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("…,e,y,d,…"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "list", - ["ldots"], - "e", - "y", - "d", - ["ldots"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "list", - ["ldots"], - "e", - "y", - "d", - ["ldots"], - ]); - }); - - cy.log("remove first comma"); - - cy.get(cesc("#\\/mi") + " textarea").type( - "{home}{rightarrow}{rightarrow}{rightarrow}{rightarrow}{rightarrow}{backspace}{backspace}f{end}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "…,f,y,d,…", - ); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("…,f,y,d,…"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "list", - ["ldots"], - "f", - "y", - "d", - ["ldots"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "list", - ["ldots"], - "f", - "y", - "d", - ["ldots"], - ]); - }); - - cy.log("remove last comma"); - - cy.get(cesc("#\\/mi") + " textarea").type( - "{end}{leftarrow}{backspace}{backspace}g{end}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "…,f,y,g,…", - ); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("…,f,y,g,…"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "list", - ["ldots"], - "f", - "y", - "g", - ["ldots"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "list", - ["ldots"], - "f", - "y", - "g", - ["ldots"], - ]); - }); - }); - - it("mathinput eliminates multicharacter symbols", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x2 - xyz - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/varWithNum")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2"); - }); - cy.get(cesc(`#\\/varWithNum2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x2", - ); - }); - cy.get(cesc("#\\/varWithNum3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x2"); - }); - cy.get(cesc("#\\/noSplit")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc(`#\\/noSplit2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc("#\\/noSplit3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/varWithNum"].stateValues.value).eq("x2"); - expect(stateVariables["/varWithNum2"].stateValues.value).eq("x2"); - expect(stateVariables["/varWithNum3"].stateValues.value).eq("x2"); - expect(stateVariables["/noSplit"].stateValues.value).eq("xyz"); - expect(stateVariables["/noSplit2"].stateValues.value).eq("xyz"); - expect(stateVariables["/noSplit3"].stateValues.value).eq("xyz"); - }); - - cy.get(cesc("#\\/varWithNum2") + " textarea").type( - "{end}{backspace}u9j{enter}", - { force: true }, - ); - cy.get(cesc("#\\/noSplit2") + " textarea").type( - "{end}{backspace}uv{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/varWithNum") + " .mjx-mrow").should( - "contain.text", - "xu9j", - ); - cy.get(cesc(`#\\/varWithNum2`) + ` .mq-editable-field`).should( - "contain.text", - "xu9j", - ); - cy.get(cesc("#\\/varWithNum3") + " .mjx-mrow").should( - "contain.text", - "xu9j", - ); - cy.get(cesc("#\\/noSplit") + " .mjx-mrow").should( - "contain.text", - "xyuv", - ); - cy.get(cesc(`#\\/noSplit2`) + ` .mq-editable-field`).should( - "contain.text", - "xyuv", - ); - cy.get(cesc("#\\/noSplit3") + " .mjx-mrow").should( - "contain.text", - "xyuv", - ); - - cy.get(cesc("#\\/varWithNum")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xu9j"); - }); - cy.get(cesc(`#\\/varWithNum2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xu9j", - ); - }); - cy.get(cesc("#\\/varWithNum3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xu9j"); - }); - cy.get(cesc("#\\/noSplit")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - cy.get(cesc(`#\\/noSplit2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyuv", - ); - }); - cy.get(cesc("#\\/noSplit3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyuv"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/varWithNum"].stateValues.value).eq("xu9j"); - expect(stateVariables["/varWithNum2"].stateValues.value).eq("xu9j"); - expect(stateVariables["/varWithNum3"].stateValues.value).eq("xu9j"); - expect(stateVariables["/noSplit"].stateValues.value).eq("xyuv"); - expect(stateVariables["/noSplit2"].stateValues.value).eq("xyuv"); - expect(stateVariables["/noSplit3"].stateValues.value).eq("xyuv"); - }); - }); - - it("mathinput prefills", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- A \\cup B - A union B - xy - xy - h(x) - h(x) - A \\cup B -

- -

- - - - - - - - $union1.value{assignNames="union1m"} - $union2.value{assignNames="union2m"} - $union3.value{assignNames="union3m"} - $union4.value{assignNames="union4m"} - $union5.value{assignNames="union5m"} - $union6.value{assignNames="union6m"} - $union7.value{assignNames="union7m"} -

- -

- - - - - - - - - $splits1.value{assignNames="splits1m"} - $splits2.value{assignNames="splits2m"} - $splits3.value{assignNames="splits3m"} - $splits4.value{assignNames="splits4m"} - $splits5.value{assignNames="splits5m"} - $splits6.value{assignNames="splits6m"} - $splits7.value{assignNames="splits7m"} - $splits8.value{assignNames="splits8m"} -

- -

- - - - - - - - - $hFunction1.value{assignNames="hFunction1m"} - $hFunction2.value{assignNames="hFunction2m"} - $hFunction3.value{assignNames="hFunction3m"} - $hFunction4.value{assignNames="hFunction4m"} - $hFunction5.value{assignNames="hFunction5m"} - $hFunction6.value{assignNames="hFunction6m"} - $hFunction7.value{assignNames="hFunction7m"} - $hFunction8.value{assignNames="hFunction8m"} -

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/union1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AβˆͺB", - ); - }); - cy.get(cesc(`#\\/union2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AβˆͺB", - ); - }); - cy.get(cesc(`#\\/union3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AβˆͺB", - ); - }); - cy.get(cesc(`#\\/union4`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AβˆͺB", - ); - }); - cy.get(cesc(`#\\/union5`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AβˆͺB", - ); - }); - cy.get(cesc(`#\\/union6`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AβˆͺB", - ); - }); - cy.get(cesc(`#\\/union7`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AβˆͺB", - ); - }); - cy.get(cesc("#\\/union1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - cy.get(cesc("#\\/union2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - cy.get(cesc("#\\/union3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - cy.get(cesc("#\\/union4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - cy.get(cesc("#\\/union5m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - cy.get(cesc("#\\/union6m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - cy.get(cesc("#\\/union7m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/union1"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union2"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union3"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union4"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union5"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union6"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union7"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union1m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union2m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union3m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union4m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union5m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union6m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/union7m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - }); - - cy.get(cesc(`#\\/splits1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/splits2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/splits3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/splits4`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/splits5`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/splits6`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/splits7`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc(`#\\/splits8`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xy", - ); - }); - cy.get(cesc("#\\/splits1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/splits2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/splits3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/splits4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/splits5m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/splits6m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/splits7m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - cy.get(cesc("#\\/splits8m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xy"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/splits1"].stateValues.value).eqls("xy"); - expect(stateVariables["/splits2"].stateValues.value).eqls("xy"); - expect(stateVariables["/splits3"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/splits4"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/splits5"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/splits6"].stateValues.value).eqls("xy"); - expect(stateVariables["/splits7"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/splits8"].stateValues.value).eqls("xy"); - expect(stateVariables["/splits1m"].stateValues.value).eqls("xy"); - expect(stateVariables["/splits2m"].stateValues.value).eqls("xy"); - expect(stateVariables["/splits3m"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/splits4m"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/splits5m"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/splits6m"].stateValues.value).eqls("xy"); - expect(stateVariables["/splits7m"].stateValues.value).eqls([ - "*", - "x", - "y", - ]); - expect(stateVariables["/splits8m"].stateValues.value).eqls("xy"); - }); - - cy.get(cesc("#\\/splits1") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/splits2") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/splits3") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/splits4") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/splits5") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/splits6") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/splits7") + " textarea").type("{end}z{enter}", { - force: true, - }); - cy.get(cesc("#\\/splits8") + " textarea").type("{end}z{enter}", { - force: true, - }); - - cy.get(cesc(`#\\/splits1`) + ` .mq-editable-field`).should( - "contain.text", - "xyz", - ); - cy.get(cesc(`#\\/splits2`) + ` .mq-editable-field`).should( - "contain.text", - "xyz", - ); - cy.get(cesc(`#\\/splits3`) + ` .mq-editable-field`).should( - "contain.text", - "xyz", - ); - cy.get(cesc(`#\\/splits4`) + ` .mq-editable-field`).should( - "contain.text", - "xyz", - ); - cy.get(cesc(`#\\/splits5`) + ` .mq-editable-field`).should( - "contain.text", - "xyz", - ); - cy.get(cesc(`#\\/splits6`) + ` .mq-editable-field`).should( - "contain.text", - "xyz", - ); - cy.get(cesc(`#\\/splits7`) + ` .mq-editable-field`).should( - "contain.text", - "xyz", - ); - cy.get(cesc(`#\\/splits8`) + ` .mq-editable-field`).should( - "contain.text", - "xyz", - ); - cy.get(cesc("#\\/splits1m") + " .mjx-mrow").should( - "contain.text", - "xyz", - ); - cy.get(cesc("#\\/splits2m") + " .mjx-mrow").should( - "contain.text", - "xyz", - ); - cy.get(cesc("#\\/splits3m") + " .mjx-mrow").should( - "contain.text", - "xyz", - ); - cy.get(cesc("#\\/splits4m") + " .mjx-mrow").should( - "contain.text", - "xyz", - ); - cy.get(cesc("#\\/splits5m") + " .mjx-mrow").should( - "contain.text", - "xyz", - ); - cy.get(cesc("#\\/splits6m") + " .mjx-mrow").should( - "contain.text", - "xyz", - ); - cy.get(cesc("#\\/splits7m") + " .mjx-mrow").should( - "contain.text", - "xyz", - ); - cy.get(cesc("#\\/splits8m") + " .mjx-mrow").should( - "contain.text", - "xyz", - ); - - cy.get(cesc(`#\\/splits1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc(`#\\/splits2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc(`#\\/splits3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc(`#\\/splits4`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc(`#\\/splits5`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc(`#\\/splits6`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc(`#\\/splits7`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc(`#\\/splits8`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "xyz", - ); - }); - cy.get(cesc("#\\/splits1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/splits2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/splits3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/splits4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/splits5m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/splits6m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/splits7m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - cy.get(cesc("#\\/splits8m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("xyz"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/splits1"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/splits2"].stateValues.value).eqls("xyz"); - expect(stateVariables["/splits3"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/splits4"].stateValues.value).eqls("xyz"); - expect(stateVariables["/splits5"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/splits6"].stateValues.value).eqls("xyz"); - expect(stateVariables["/splits7"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/splits8"].stateValues.value).eqls("xyz"); - expect(stateVariables["/splits1m"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/splits2m"].stateValues.value).eqls("xyz"); - expect(stateVariables["/splits3m"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/splits4m"].stateValues.value).eqls("xyz"); - expect(stateVariables["/splits5m"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/splits6m"].stateValues.value).eqls("xyz"); - expect(stateVariables["/splits7m"].stateValues.value).eqls([ - "*", - "x", - "y", - "z", - ]); - expect(stateVariables["/splits8m"].stateValues.value).eqls("xyz"); - }); - - cy.get(cesc(`#\\/hFunction1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(x)", - ); - }); - cy.get(cesc(`#\\/hFunction2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(x)", - ); - }); - cy.get(cesc(`#\\/hFunction3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "hx", - ); - }); - cy.get(cesc(`#\\/hFunction4`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "hx", - ); - }); - cy.get(cesc(`#\\/hFunction5`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "hx", - ); - }); - cy.get(cesc(`#\\/hFunction6`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(x)", - ); - }); - cy.get(cesc(`#\\/hFunction7`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(x)", - ); - }); - cy.get(cesc(`#\\/hFunction8`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(x)", - ); - }); - cy.get(cesc("#\\/hFunction1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(x)"); - }); - cy.get(cesc("#\\/hFunction2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(x)"); - }); - cy.get(cesc("#\\/hFunction3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hx"); - }); - cy.get(cesc("#\\/hFunction4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hx"); - }); - cy.get(cesc("#\\/hFunction5m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hx"); - }); - cy.get(cesc("#\\/hFunction6m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(x)"); - }); - cy.get(cesc("#\\/hFunction7m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hx"); - }); - cy.get(cesc("#\\/hFunction8m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(x)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/hFunction1"].stateValues.value).eqls([ - "apply", - "h", - "x", - ]); - expect(stateVariables["/hFunction2"].stateValues.value).eqls([ - "apply", - "h", - "x", - ]); - expect(stateVariables["/hFunction3"].stateValues.value).eqls([ - "*", - "h", - "x", - ]); - expect(stateVariables["/hFunction4"].stateValues.value).eqls([ - "*", - "h", - "x", - ]); - expect(stateVariables["/hFunction5"].stateValues.value).eqls([ - "*", - "h", - "x", - ]); - expect(stateVariables["/hFunction6"].stateValues.value).eqls([ - "apply", - "h", - "x", - ]); - expect(stateVariables["/hFunction7"].stateValues.value).eqls([ - "*", - "h", - "x", - ]); - expect(stateVariables["/hFunction8"].stateValues.value).eqls([ - "apply", - "h", - "x", - ]); - expect(stateVariables["/hFunction1m"].stateValues.value).eqls([ - "apply", - "h", - "x", - ]); - expect(stateVariables["/hFunction2m"].stateValues.value).eqls([ - "apply", - "h", - "x", - ]); - expect(stateVariables["/hFunction3m"].stateValues.value).eqls([ - "*", - "h", - "x", - ]); - expect(stateVariables["/hFunction4m"].stateValues.value).eqls([ - "*", - "h", - "x", - ]); - expect(stateVariables["/hFunction5m"].stateValues.value).eqls([ - "*", - "h", - "x", - ]); - expect(stateVariables["/hFunction6m"].stateValues.value).eqls([ - "apply", - "h", - "x", - ]); - expect(stateVariables["/hFunction7m"].stateValues.value).eqls([ - "*", - "h", - "x", - ]); - expect(stateVariables["/hFunction8m"].stateValues.value).eqls([ - "apply", - "h", - "x", - ]); - }); - - cy.get(cesc("#\\/hFunction1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(y){enter}", - { force: true }, - ); - cy.get(cesc("#\\/hFunction2") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(y){enter}", - { force: true }, - ); - cy.get(cesc("#\\/hFunction3") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(y){enter}", - { force: true }, - ); - cy.get(cesc("#\\/hFunction4") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(y){enter}", - { force: true }, - ); - cy.get(cesc("#\\/hFunction5") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(y){enter}", - { force: true }, - ); - cy.get(cesc("#\\/hFunction6") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(y){enter}", - { force: true }, - ); - cy.get(cesc("#\\/hFunction7") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(y){enter}", - { force: true }, - ); - cy.get(cesc("#\\/hFunction8") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}h(y){enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/hFunction1`) + ` .mq-editable-field`).should( - "contain.text", - "h(y)", - ); - cy.get(cesc(`#\\/hFunction2`) + ` .mq-editable-field`).should( - "contain.text", - "h(y)", - ); - cy.get(cesc(`#\\/hFunction3`) + ` .mq-editable-field`).should( - "contain.text", - "h(y)", - ); - cy.get(cesc(`#\\/hFunction4`) + ` .mq-editable-field`).should( - "contain.text", - "h(y)", - ); - cy.get(cesc(`#\\/hFunction5`) + ` .mq-editable-field`).should( - "contain.text", - "h(y)", - ); - cy.get(cesc(`#\\/hFunction6`) + ` .mq-editable-field`).should( - "contain.text", - "h(y)", - ); - cy.get(cesc(`#\\/hFunction7`) + ` .mq-editable-field`).should( - "contain.text", - "h(y)", - ); - cy.get(cesc(`#\\/hFunction8`) + ` .mq-editable-field`).should( - "contain.text", - "h(y)", - ); - cy.get(cesc("#\\/hFunction1m") + " .mjx-mrow").should( - "contain.text", - "hy", - ); - cy.get(cesc("#\\/hFunction2m") + " .mjx-mrow").should( - "contain.text", - "h(y)", - ); - cy.get(cesc("#\\/hFunction3m") + " .mjx-mrow").should( - "contain.text", - "hy", - ); - cy.get(cesc("#\\/hFunction4m") + " .mjx-mrow").should( - "contain.text", - "h(y)", - ); - cy.get(cesc("#\\/hFunction5m") + " .mjx-mrow").should( - "contain.text", - "hy", - ); - cy.get(cesc("#\\/hFunction6m") + " .mjx-mrow").should( - "contain.text", - "h(y)", - ); - cy.get(cesc("#\\/hFunction7m") + " .mjx-mrow").should( - "contain.text", - "hy", - ); - cy.get(cesc("#\\/hFunction8m") + " .mjx-mrow").should( - "contain.text", - "h(y)", - ); - - cy.get(cesc(`#\\/hFunction1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(y)", - ); - }); - cy.get(cesc(`#\\/hFunction2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(y)", - ); - }); - cy.get(cesc(`#\\/hFunction3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(y)", - ); - }); - cy.get(cesc(`#\\/hFunction4`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(y)", - ); - }); - cy.get(cesc(`#\\/hFunction5`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(y)", - ); - }); - cy.get(cesc(`#\\/hFunction6`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(y)", - ); - }); - cy.get(cesc(`#\\/hFunction7`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(y)", - ); - }); - cy.get(cesc(`#\\/hFunction8`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(y)", - ); - }); - cy.get(cesc("#\\/hFunction1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hy"); - }); - cy.get(cesc("#\\/hFunction2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(y)"); - }); - cy.get(cesc("#\\/hFunction3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hy"); - }); - cy.get(cesc("#\\/hFunction4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(y)"); - }); - cy.get(cesc("#\\/hFunction5m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hy"); - }); - cy.get(cesc("#\\/hFunction6m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(y)"); - }); - cy.get(cesc("#\\/hFunction7m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hy"); - }); - cy.get(cesc("#\\/hFunction8m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("h(y)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/hFunction1"].stateValues.value).eqls([ - "*", - "h", - "y", - ]); - expect(stateVariables["/hFunction2"].stateValues.value).eqls([ - "apply", - "h", - "y", - ]); - expect(stateVariables["/hFunction3"].stateValues.value).eqls([ - "*", - "h", - "y", - ]); - expect(stateVariables["/hFunction4"].stateValues.value).eqls([ - "apply", - "h", - "y", - ]); - expect(stateVariables["/hFunction5"].stateValues.value).eqls([ - "*", - "h", - "y", - ]); - expect(stateVariables["/hFunction6"].stateValues.value).eqls([ - "apply", - "h", - "y", - ]); - expect(stateVariables["/hFunction7"].stateValues.value).eqls([ - "*", - "h", - "y", - ]); - expect(stateVariables["/hFunction8"].stateValues.value).eqls([ - "apply", - "h", - "y", - ]); - expect(stateVariables["/hFunction1m"].stateValues.value).eqls([ - "*", - "h", - "y", - ]); - expect(stateVariables["/hFunction2m"].stateValues.value).eqls([ - "apply", - "h", - "y", - ]); - expect(stateVariables["/hFunction3m"].stateValues.value).eqls([ - "*", - "h", - "y", - ]); - expect(stateVariables["/hFunction4m"].stateValues.value).eqls([ - "apply", - "h", - "y", - ]); - expect(stateVariables["/hFunction5m"].stateValues.value).eqls([ - "*", - "h", - "y", - ]); - expect(stateVariables["/hFunction6m"].stateValues.value).eqls([ - "apply", - "h", - "y", - ]); - expect(stateVariables["/hFunction7m"].stateValues.value).eqls([ - "*", - "h", - "y", - ]); - expect(stateVariables["/hFunction8m"].stateValues.value).eqls([ - "apply", - "h", - "y", - ]); - }); - }); - - it("prefillFromLatex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Prefill with m: \\frac{a}{b} \\int_a^b \\hat{f}(x) dx

-

Result:

-

Value: $input1

-

Raw value: $input1.rawRendererValue

- -

Prefill with phrase including "\\ "

-

Result:

-

Value: $input2

-

Raw value: $input2.rawRendererValue

- -

Prefill with a \\text

-

Result:

-

Value: $input3

-

Raw value: $input3.rawRendererValue

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/input1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "ab∫ba^f(x)dx", - ); - }); - cy.get(cesc("#\\/pv1") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/pr1")).should( - "have.text", - "Raw value: \\frac{a}{b} \\int_a^b \\hat{f}(x) dx", - ); - - cy.get(cesc(`#\\/input2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "hellothere(a)(b)", - ); - }); - cy.get(cesc("#\\/pv2") + " .mjx-mrow") - .eq(0) - .should("have.text", "hellothereab"); - cy.get(cesc("#\\/pr2")).should( - "have.text", - "Raw value: hello\\ there (a)(b)", - ); - - cy.get(cesc(`#\\/input3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "hellothere(a)(b)", - ); - }); - cy.get(cesc("#\\/pv3") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/pr3")).should( - "have.text", - "Raw value: \\text{hello there} (a)(b)", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/input1"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/input1"].stateValues.immediateValue).eq( - "\uff3f", - ); - expect(stateVariables["/input1"].stateValues.rawRendererValue).eq( - "\\frac{a}{b} \\int_a^b \\hat{f}(x) dx", - ); - expect(stateVariables["/input2"].stateValues.value).eqls([ - "*", - "h", - "e", - "l", - "l", - "o", - "t", - "h", - "e", - "r", - "e", - "a", - "b", - ]); - expect(stateVariables["/input2"].stateValues.immediateValue).eqls([ - "*", - "h", - "e", - "l", - "l", - "o", - "t", - "h", - "e", - "r", - "e", - "a", - "b", - ]); - expect(stateVariables["/input2"].stateValues.rawRendererValue).eq( - "hello\\ there (a)(b)", - ); - expect(stateVariables["/input3"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/input3"].stateValues.immediateValue).eq( - "\uff3f", - ); - expect(stateVariables["/input3"].stateValues.rawRendererValue).eq( - "\\text{hello there} (a)(b)", - ); - }); - - cy.get(cesc("#\\/input1") + " textarea").type( - "{ctrl+end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}f{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pv1") + " .mjx-mrow").should( - "contain.text", - "(ab)∫baf(x)dx", - ); - cy.get(cesc(`#\\/input1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "ab∫baf(x)dx", - ); - }); - cy.get(cesc("#\\/pr1")).should( - "have.text", - "Raw value: \\frac{a}{b}\\int_a^bf(x)dx", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - // expect(stateVariables['/input1'].stateValues.value).eqls(["*", ["/", "a", "b"], "a", ["apply", "f", "x"], "d", "x"]) - // expect(stateVariables['/input1'].stateValues.immediateValue).eqls(["*", ["/", "a", "b"], "a", ["apply", "f", "x"], "d", "x"]) - expect(stateVariables["/input1"].stateValues.rawRendererValue).eq( - "\\frac{a}{b}\\int_a^bf(x)dx", - ); - }); - - cy.get(cesc("#\\/input2") + " textarea").type( - "{ctrl+end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pv2") + " .mjx-mrow").should( - "contain.text", - "helloab", - ); - cy.get(cesc(`#\\/input2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "hello(a)(b)", - ); - }); - cy.get(cesc("#\\/pr2")).should("have.text", "Raw value: hello(a)(b)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/input2"].stateValues.value).eqls([ - "*", - "h", - "e", - "l", - "l", - "o", - "a", - "b", - ]); - expect(stateVariables["/input2"].stateValues.immediateValue).eqls([ - "*", - "h", - "e", - "l", - "l", - "o", - "a", - "b", - ]); - expect(stateVariables["/input2"].stateValues.rawRendererValue).eq( - "hello(a)(b)", - ); - }); - - cy.get(cesc("#\\/input3") + " textarea").type( - "{ctrl+end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{backspace}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pr3")).should( - "have.text", - "Raw value: \\text{h}(a)(b)", - ); - cy.get(cesc(`#\\/input3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "h(a)(b)", - ); - }); - cy.get(cesc("#\\/pv3") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/input3"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/input3"].stateValues.immediateValue).eq( - "\uff3f", - ); - expect(stateVariables["/input3"].stateValues.rawRendererValue).eq( - "\\text{h}(a)(b)", - ); - }); - - cy.get(cesc("#\\/input3") + " textarea").type("{backspace}{enter}", { - force: true, - }); - - cy.get(cesc("#\\/pv3") + " .mjx-mrow").should("contain.text", "ab"); - cy.get(cesc(`#\\/input3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "(a)(b)", - ); - }); - cy.get(cesc("#\\/pr3")).should("have.text", "Raw value: (a)(b)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/input3"].stateValues.value).eqls([ - "*", - "a", - "b", - ]); - expect(stateVariables["/input3"].stateValues.immediateValue).eqls([ - "*", - "a", - "b", - ]); - expect(stateVariables["/input3"].stateValues.rawRendererValue).eq( - "(a)(b)", - ); - }); - }); - - it("convert and/or into logicals", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "\uff3f"); - - cy.log("equalities with or"); - cy.get(cesc("#\\/mi") + " textarea").type("x=1 or u=x{enter}", { - force: true, - }); - - // cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`).should('contain.text', 'x=1 or u=x'); - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "(x=1)∨(u=x)", - ); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x=1oru=x", - ); - }); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x=1)∨(u=x)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "or", - ["=", "x", 1], - ["=", "u", "x"], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "or", - ["=", "x", 1], - ["=", "u", "x"], - ]); - }); - - cy.log("inequalities with and"); - cy.get(cesc("#\\/mi") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}x>3 and x <= 5{enter}", - { force: true }, - ); - - // cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`).should('contain.text', 'x>3 and x≀5'); - cy.get(cesc("#\\/m") + " .mjx-mrow").should( - "contain.text", - "(x>3)∧(x≀5)", - ); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "x>3andx≀5", - ); - }); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x>3)∧(x≀5)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "and", - [">", "x", 3], - ["le", "x", 5], - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "and", - [">", "x", 3], - ["le", "x", 5], - ]); - }); - - cy.log(`don't convert if not word`); - cy.get(cesc("#\\/mi") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}AandBorC{enter}", - { force: true }, - ); - - // cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`).should('contain.text', 'AandBorC'); - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "AandBorC"); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AandBorC", - ); - }); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AandBorC"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "*", - "A", - "a", - "n", - "d", - "B", - "o", - "r", - "C", - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - "A", - "a", - "n", - "d", - "B", - "o", - "r", - "C", - ]); - }); - - cy.log(`add parens or spaces`); - cy.get(cesc("#\\/mi") + " textarea").type( - "{home}({rightArrow}){rightArrow}{rightArrow}{rightArrow} {rightArrow} {rightArrow}{rightArrow}({rightArrow}){enter}", - { force: true }, - ); - - // cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`).should('contain.text', '(A)and B or(C)'); - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "(A∧B)∨C"); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "(A)andBor(C)", - ); - }); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(A∧B)∨C"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "or", - ["and", "A", "B"], - "C", - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "or", - ["and", "A", "B"], - "C", - ]); - }); - }); - - it("union from U", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

Value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "\uff3f"); - - cy.log("A U C without unionFromU"); - cy.get(cesc("#\\/mi") + " textarea").type("A U C{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "AUC"); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AUC", - ); - }); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AUC"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "*", - "A", - "U", - "C", - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - "A", - "U", - "C", - ]); - }); - - cy.log("active unionFromU and modify text"); - cy.get(cesc("#\\/ufu")).click(); - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}B{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "AβˆͺB"); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AUB", - ); - }); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - }); - - cy.log("no substitution without spaces"); - cy.get(cesc("#\\/mi") + " textarea").type( - "{end}{leftArrow}{backspace}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "AUB"); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AUB", - ); - }); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AUB"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "*", - "A", - "U", - "B", - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - "A", - "U", - "B", - ]); - }); - - cy.log("add parens"); - cy.get(cesc("#\\/mi") + " textarea").type( - "{end}){leftArrow}{leftArrow}({enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "AβˆͺB"); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "AU(B)", - ); - }); - - cy.get(cesc("#\\/m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("AβˆͺB"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - expect(stateVariables["/m"].stateValues.value).eqls([ - "union", - "A", - "B", - ]); - }); - }); - - it("mathinput can merge coordinates", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- - - - -

Change x-coordinate:

-

Change y-coordinate:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/x1") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.get(cesc("#\\/coords") + " .mq-editable-field").should( - "have.text", - "(3,2)", - ); - - cy.get(cesc("#\\/x2") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - - cy.get(cesc("#\\/coords") + " .mq-editable-field").should( - "have.text", - "(3,4)", - ); - }); - - it("mathinput can merge coordinates, immediateValue", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- - - - -

Change x-coordinate:

-

Change y-coordinate:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/x1") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.get(cesc("#\\/coords") + " .mq-editable-field").should( - "have.text", - "(3,2)", - ); - - cy.get(cesc("#\\/x2") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - - cy.get(cesc("#\\/coords") + " .mq-editable-field").should( - "have.text", - "(3,4)", - ); - }); - - it("change prefill", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

-

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

-

Prefill:

-

Change prefill:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("(1,2)"); - }); - cy.get(cesc("#\\/m") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("(1,2)"); - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "(1,2)", - ); - cy.get(cesc("#\\/mipf") + " .mq-editable-field").should( - "have.text", - "(1,2)", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "tuple", - 1, - 2, - ]); - expect(stateVariables["/mi"].stateValues.prefill).eqls([ - "tuple", - 1, - 2, - ]); - }); - - cy.log("change prefill"); - - cy.get(cesc("#\\/mipf") + " textarea") - .type("{end}{leftArrow}{backspace}5{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "(1,5)", - ); - cy.get(cesc("#\\/mipf") + " .mq-editable-field").should( - "have.text", - "(1,5)", - ); - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "(1,5)"); - cy.get(cesc("#\\/pf") + " .mjx-mrow").should("contain.text", "(1,5)"); - - cy.get(cesc("#\\/m") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("(1,5)"); - }); - cy.get(cesc("#\\/pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("(1,5)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "tuple", - 1, - 5, - ]); - expect(stateVariables["/mi"].stateValues.prefill).eqls([ - "tuple", - 1, - 5, - ]); - }); - - cy.log("change value"); - - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}{leftArrow}{backspace}9{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "(1,9)"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "(1,9)", - ); - cy.get(cesc("#\\/mipf") + " .mq-editable-field").should( - "have.text", - "(1,5)", - ); - cy.get(cesc("#\\/pf") + " .mjx-mrow").should("contain.text", "(1,5)"); - cy.get(cesc("#\\/m") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("(1,9)"); - }); - cy.get(cesc("#\\/pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("(1,5)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "tuple", - 1, - 9, - ]); - expect(stateVariables["/mi"].stateValues.prefill).eqls([ - "tuple", - 1, - 5, - ]); - }); - - cy.log("change prefill again"); - - cy.get(cesc("#\\/mipf") + " textarea") - .type("{end}{leftArrow}{backspace}7{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/pf") + " .mjx-mrow").should("contain.text", "(1,7)"); - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "(1,9)"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "(1,9)", - ); - cy.get(cesc("#\\/mipf") + " .mq-editable-field").should( - "have.text", - "(1,7)", - ); - cy.get(cesc("#\\/pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("(1,7)"); - }); - cy.get(cesc("#\\/m") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("(1,9)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "tuple", - 1, - 9, - ]); - expect(stateVariables["/mi"].stateValues.prefill).eqls([ - "tuple", - 1, - 7, - ]); - }); - }); - - it("check ignoreUpdate bug 1", () => { - // if set core to delay 1 second on updates - // then the refresh on blur (from the focus field recoil atoms changing) - // would cause rendererValue.current to be changed to the old SV value - // as the update wouldn't be ignored - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

n:

-

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

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - // by highlighting and typing a number, we make sure the rendererValue changes directly - // from 10 to 20 and back to 10 (without other changes that would hide the bug) - cy.get(cesc("#\\/n") + " textarea") - .type("{home}{shift+rightArrow}2", { force: true }) - .blur(); - cy.get(cesc("#\\/n2")).should("contain.text", "20"); - - cy.get(cesc("#\\/n") + " textarea") - .type("{home}{shift+rightArrow}1", { force: true }) - .blur(); - cy.get(cesc("#\\/n2")).should("contain.text", "10"); - }); - - it("check ignoreUpdate bug 2", () => { - // if set core to delay 1 second on updates - // the extra update from focusing another mathinput wasn't being ignored - // leading rendererValue to get out of sync - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

c:

-

c2: $c.value{assignNames="c2"}

-

d:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/c2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - - cy.get(cesc("#\\/c") + " textarea").type("{end}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/d") + " textarea").focus(); - - cy.get(cesc("#\\/c2")).should("contain.text", "xy"); - cy.get(cesc("#\\/c") + " .mq-editable-field").should( - "contain.text", - "xy", - ); - cy.get(cesc("#\\/c2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("xy"); - }); - - // need next update to go back to x for the bug to be revealed - cy.get(cesc("#\\/c") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - cy.get(cesc("#\\/c2")).should("not.contain.text", "xy"); - cy.get(cesc("#\\/c") + " .mq-editable-field").should( - "contain.text", - "x", - ); - cy.get(cesc("#\\/c2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - }); - - it("mathinput with number child", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

-

Value: $mi.value{assignNames="mv"}

-

Immediate Value: $mi.immediateValue{assignNames="miv"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", ""); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(NaN); - }); - - cy.log("type a number"); - cy.get(cesc("#\\/mi") + " textarea").type("5", { force: true }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(5); - }); - - cy.log("hit enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(5); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(5); - }); - - cy.log("type pi"); - // for some reason, need a significant delay in between keystrokes - // or MathJax doesn't render immediate value correctly. - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}pi", { - force: true, - delay: 100, - }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "Ο€"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("Ο€"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("Ο€"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(5); - expect(stateVariables["/miv"].stateValues.value).eqls("pi"); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should( - "contain.text", - "3.141592654", - ); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should( - "contain.text", - "3.141592654", - ); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3.141592654", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(Math.PI); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - Math.PI, - ); - }); - - cy.log("type x"); - cy.get(cesc("#\\/mi") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x", - { force: true }, - ); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "x"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(Math.PI); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls("x"); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "NaN"); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "NaN"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(NaN); - }); - - cy.log("type 2/3"); - cy.get(cesc("#\\/mi") + " textarea").type("2/3", { force: true }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "23"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("23"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "23", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "/", - 2, - 3, - ]); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should( - "contain.text", - "0.6666666667", - ); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should( - "contain.text", - "0.6666666667", - ); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0.6666666667"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0.6666666667"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "0.6666666667", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(2 / 3); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - 2 / 3, - ); - }); - }); - - it("mathinput with number child, do not hide NaN", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

-

Value: $mi.value{assignNames="mv"}

-

Immediate Value: $mi.immediateValue{assignNames="miv"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "NaN", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(NaN); - }); - - cy.log("type a number"); - // for some reason, need a significant delay in between keystrokes - // or MathJax doesn't render immediate value correctly. - cy.wait(1000); - cy.get(cesc("#\\/mi") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}5", - { force: true, delay: 200 }, - ); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(5); - }); - - cy.log("hit enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(5); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(5); - }); - - cy.log("type pi"); - // for some reason, need a significant delay in between keystrokes - // or MathJax doesn't render immediate value correctly. - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}pi", { - force: true, - delay: 100, - }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "Ο€"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("Ο€"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("Ο€"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(5); - expect(stateVariables["/miv"].stateValues.value).eqls("pi"); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should( - "contain.text", - "3.141592654", - ); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should( - "contain.text", - "3.141592654", - ); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3.141592654", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(Math.PI); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - Math.PI, - ); - }); - - cy.log("type x"); - cy.get(cesc("#\\/mi") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x", - { force: true }, - ); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "x"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(Math.PI); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls("x"); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "NaN"); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "NaN"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "NaN", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(NaN); - }); - - cy.log("type 2/3"); - cy.get(cesc("#\\/mi") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}2/3", - { force: true }, - ); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "23"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("23"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "23", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "/", - 2, - 3, - ]); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should( - "contain.text", - "0.6666666667", - ); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should( - "contain.text", - "0.6666666667", - ); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0.6666666667"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0.6666666667"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "0.6666666667", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(2 / 3); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - 2 / 3, - ); - }); - }); - - it("mathinput with number child, value on NaN", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

-

Value: $mi.value{assignNames="mv"}

-

Immediate Value: $mi.immediateValue{assignNames="miv"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0"); - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(0); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(0); - }); - - cy.log("type a number"); - // for some reason, need a significant delay in between keystrokes - // or MathJax doesn't render immediate value correctly. - cy.wait(1000); - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}5", { - force: true, - delay: 200, - }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(0); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(5); - }); - - cy.log("hit enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(5); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(5); - }); - - cy.log("type pi"); - // for some reason, need a significant delay in between keystrokes - // or MathJax doesn't render immediate value correctly. - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}pi", { - force: true, - delay: 100, - }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "Ο€"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("Ο€"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("Ο€"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(5); - expect(stateVariables["/miv"].stateValues.value).eqls("pi"); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should( - "contain.text", - "3.141592654", - ); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should( - "contain.text", - "3.141592654", - ); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "3.141592654", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(Math.PI); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - Math.PI, - ); - }); - - cy.log("type x"); - cy.get(cesc("#\\/mi") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x", - { force: true }, - ); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "x"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3.141592654"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(Math.PI); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls("x"); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "0"); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "0"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(0); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(0); - }); - - cy.log("type 2/3"); - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}2/3", { - force: true, - }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "23"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("23"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "23", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(0); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "/", - 2, - 3, - ]); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should( - "contain.text", - "0.6666666667", - ); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should( - "contain.text", - "0.6666666667", - ); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0.6666666667"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("0.6666666667"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "0.6666666667", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(2 / 3); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - 2 / 3, - ); - }); - }); - - it("mathinput with number child, force positive integer", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

- -

-

Value: $mi.value{assignNames="mv"}

-

Immediate Value: $mi.immediateValue{assignNames="miv"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", ""); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(NaN); - }); - - cy.log("type a number"); - cy.get(cesc("#\\/mi") + " textarea").type("5", { force: true }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(5); - }); - - cy.log("hit enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(5); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(5); - }); - - cy.log("type pi"); - // for some reason, need a significant delay in between keystrokes - // or MathJax doesn't render immediate value correctly. - cy.get(cesc("#\\/mi") + " textarea").type("{end}{backspace}pi", { - force: true, - delay: 50, - }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "Ο€"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("5"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("Ο€"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("Ο€"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(5); - expect(stateVariables["/miv"].stateValues.value).eqls("pi"); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "3"); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "3"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("3"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(3); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(3); - }); - - cy.log("type x"); - cy.get(cesc("#\\/mi") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x", - { force: true }, - ); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "x"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("3"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("x"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(3); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls("x"); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "NaN"); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "NaN"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(NaN); - }); - - cy.log("type -3"); - cy.get(cesc("#\\/mi") + " textarea").type("-3", { force: true }); - - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "βˆ’3"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("NaN"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("βˆ’3"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "βˆ’3", - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(-3); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc("#\\/mv") + " .mjx-mrow").should("contain.text", "1"); - cy.get(cesc("#\\/miv") + " .mjx-mrow").should("contain.text", "1"); - - cy.get(cesc("#\\/mv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1"); - }); - cy.get(cesc("#\\/miv") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("1"); - }); - - cy.get(cesc(`#\\/mi`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls(1); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls(1); - }); - }); - - it("copy raw renderer value, handle incomplete math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/rv")).should("have.text", ""); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", ""); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls("\uff3f"); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - "\uff3f", - ); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls(""); - expect(stateVariables["/rv"].stateValues.value).eqls(""); - }); - - cy.log("enter value that parses to math"); - cy.get(cesc("#\\/mi") + " textarea") - .type("a", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "a"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls("a"); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls("a"); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "a", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("a"); - }); - - cy.log("enter value that is incomplete in math"); - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}^", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "a^{ }"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "^", - "a", - "\uff3f", - ]); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "^", - "a", - "\uff3f", - ]); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "a^{ }", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("a^{ }"); - }); - - cy.log("still have incomplete math"); - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}{leftArrow}bc+", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "a^{bc+}"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "abc+", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "^", - "a", - ["+", ["*", "b", "c"], "\uff3f"], - ]); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "^", - "a", - ["+", ["*", "b", "c"], "\uff3f"], - ]); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "a^{bc+}", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("a^{bc+}"); - }); - - cy.log("complete to valid math"); - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}{leftArrow}d", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "a^{bc+d}"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "abc+d", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "^", - "a", - ["+", ["*", "b", "c"], "d"], - ]); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "^", - "a", - ["+", ["*", "b", "c"], "d"], - ]); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "a^{bc+d}", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("a^{bc+d}"); - }); - - cy.log("incomplete math again"); - cy.get(cesc("#\\/mi") + " textarea").type("{end}-{enter}", { - force: true, - }); - - cy.get(cesc("#\\/rv")).should("have.text", "a^{bc+d}-"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "contain.text", - "abc+dβˆ’", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "+", - ["^", "a", ["+", ["*", "b", "c"], "d"]], - ["-", "\uff3f"], - ]); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "+", - ["^", "a", ["+", ["*", "b", "c"], "d"]], - ["-", "\uff3f"], - ]); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "a^{bc+d}-", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("a^{bc+d}-"); - }); - - cy.log("complete to valid math again"); - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}e", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "a^{bc+d}-e"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "abc+dβˆ’e", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "+", - ["^", "a", ["+", ["*", "b", "c"], "d"]], - ["-", "e"], - ]); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "+", - ["^", "a", ["+", ["*", "b", "c"], "d"]], - ["-", "e"], - ]); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "a^{bc+d}-e", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("a^{bc+d}-e"); - }); - }); - - it("copy raw renderer value, handle invalid math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/rv")).should("have.text", ""); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", ""); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls("\uff3f"); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - "\uff3f", - ); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls(""); - expect(stateVariables["/rv"].stateValues.value).eqls(""); - }); - - cy.log("enter value that parses to math"); - cy.get(cesc("#\\/mi") + " textarea") - .type("a", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "a"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls("a"); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls("a"); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "a", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("a"); - }); - - cy.log("enter value that is error in math"); - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}@", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "a@"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "a@", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls("\uff3f"); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - "\uff3f", - ); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "a@", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("a@"); - }); - - cy.log("still have error in math"); - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}{leftArrow}b+", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "ab+@"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "ab+@", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls("\uff3f"); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls( - "\uff3f", - ); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "ab+@", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("ab+@"); - }); - - cy.log("make valid math"); - cy.get(cesc("#\\/mi") + " textarea") - .type("{end}{backspace}c", { force: true }) - .blur(); - - cy.get(cesc("#\\/rv")).should("have.text", "ab+c"); - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "ab+c", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "+", - ["*", "a", "b"], - "c", - ]); - expect(stateVariables["/mi"].stateValues.immediateValue).eqls([ - "+", - ["*", "a", "b"], - "c", - ]); - expect(stateVariables["/mi"].stateValues.rawRendererValue).eqls( - "ab+c", - ); - expect(stateVariables["/rv"].stateValues.value).eqls("ab+c"); - }); - }); - - it("parse scientific notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/mi1") + " .mq-editable-field").should( - "have.text", - "5E+1", - ); - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "5E+1"); - cy.get(cesc("#\\/mi2") + " .mq-editable-field").should( - "have.text", - "50", - ); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "50"); - - cy.get(cesc("#\\/mi1") + " textarea") - .type("{end}{shift+home}{backspace}2xβˆ’3E+2{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should("contain.text", "2xβˆ’3E+2"); - - cy.get(cesc("#\\/mi1") + " .mq-editable-field").should( - "have.text", - "2xβˆ’3E+2", - ); - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "2xβˆ’3E+2"); - - cy.get(cesc("#\\/mi2") + " textarea") - .type("{end}{shift+home}{backspace}2x-3E+2{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/m2") + " .mjx-mrow").should("contain.text", "2xβˆ’300"); - - cy.get(cesc("#\\/mi2") + " .mq-editable-field").should( - "have.text", - "2xβˆ’3E+2", - ); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2xβˆ’300"); - }); - - it("set value from immediateValue on reload", () => { - let doenetML = ` -

- -

value: $n

-

immediate value: $n.immediateValue

- `; - - 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, - }, - "*", - ); - }); - - cy.get(cesc("#\\/n") + " textarea").type("1", { force: true }); - - cy.get(cesc("#\\/piv") + " .mjx-mrow").should("contain.text", "1"); - cy.get(cesc("#\\/piv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/pv") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.wait(1500); // wait for debounce - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#\\/pv") + " .mjx-mrow").should("contain.text", "1"); - cy.get(cesc("#\\/piv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/pv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - }); - - it("remove strings", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc("#\\/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - - cy.get(cesc("#\\/mi1") + " textarea").type("12,345{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi2") + " textarea").type("12,345{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi3") + " textarea").type("12,345{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should("contain.text", "12345"); - cy.get(cesc("#\\/m2") + " .mjx-mrow").should("contain.text", "12,345"); - cy.get(cesc("#\\/m3") + " .mjx-mrow").should("contain.text", "12345"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eq(12345); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "list", - 12, - 345, - ]); - expect(stateVariables["/mi3"].stateValues.value).eq(12345); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{end}{shift+home}{backspace}$45.23{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2") + " textarea").type( - "{end}{shift+home}{backspace}$45.23{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3") + " textarea").type( - "{end}{shift+home}{backspace}$45.23{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should("contain.text", "$45.23"); - cy.get(cesc("#\\/m2") + " .mjx-mrow").should("contain.text", "45.23"); - cy.get(cesc("#\\/m3") + " .mjx-mrow").should("contain.text", "45.23"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "unit", - "$", - 45.23, - ]); - expect(stateVariables["/mi2"].stateValues.value).eq(45.23); - expect(stateVariables["/mi3"].stateValues.value).eq(45.23); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{end}{shift+home}{backspace}78%{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2") + " textarea").type( - "{end}{shift+home}{backspace}78%{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3") + " textarea").type( - "{end}{shift+home}{backspace}78%{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should("contain.text", "78%"); - cy.get(cesc("#\\/m2") + " .mjx-mrow").should("contain.text", "78"); - cy.get(cesc("#\\/m3") + " .mjx-mrow").should("contain.text", "78"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "unit", - 78, - "%", - ]); - expect(stateVariables["/mi2"].stateValues.value).eq(78); - expect(stateVariables["/mi3"].stateValues.value).eq(78); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type( - `{end}{shift+home}{backspace}$34,000%dx{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/mi2") + " textarea").type( - `{end}{shift+home}{backspace}$34,000%dx{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/mi3") + " textarea").type( - `{end}{shift+home}{backspace}$34,000%dx{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should( - "contain.text", - "$(34000%)dx", - ); - cy.get(cesc("#\\/m2") + " .mjx-mrow").should("contain.text", "34,0dx"); - cy.get(cesc("#\\/m3") + " .mjx-mrow").should("contain.text", "34000"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "unit", - "$", - ["*", ["unit", 34000, "%"], "d", "x"], - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "list", - 34, - ["*", 0, "d", "x"], - ]); - expect(stateVariables["/mi3"].stateValues.value).eq(34000); - }); - }); - - it("mathinput updates not messed up with invalid child logic containing a composite", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -
    - x $m -
  1. -
- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc("#\\/mi") + " textarea").type("sqrt4{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m2") + " .mjx-mrow").should("contain.text", "√4"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "√4"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi"].stateValues.value).eqls([ - "apply", - "sqrt", - 4, - ]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "apply", - "sqrt", - 4, - ]); - }); - }); - - it("minWidth attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Specify min width:

- -

Result:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/mw") + " .mq-editable-field").should( - "have.css", - "min-width", - "50px", - ); - - cy.get(cesc("#\\/result") + " .mq-editable-field").should( - "have.css", - "min-width", - "0px", - ); - - cy.get(cesc("#\\/mw") + " textarea").type( - "{end}{backspace}100{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/result") + " .mq-editable-field").should( - "have.css", - "min-width", - "100px", - ); - - cy.get(cesc("#\\/mw") + " textarea").type( - "{end}{backspace}{backspace}{backspace}{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result") + " .mq-editable-field").should( - "have.css", - "min-width", - "0px", - ); - - cy.get(cesc("#\\/mw") + " textarea").type("{end}{backspace}40{enter}", { - force: true, - }); - cy.get(cesc("#\\/result") + " .mq-editable-field").should( - "have.css", - "min-width", - "40px", - ); - - cy.get(cesc("#\\/mw") + " textarea").type("{end}x{enter}", { - force: true, - }); - cy.get(cesc("#\\/result") + " .mq-editable-field").should( - "have.css", - "min-width", - "0px", - ); - - cy.get(cesc("#\\/mw") + " textarea").type( - "{end}{backspace}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result") + " .mq-editable-field").should( - "have.css", - "min-width", - "47px", - ); - - cy.get(cesc("#\\/mw") + " textarea").type( - "{end}{backspace}{backspace}-20{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result") + " .mq-editable-field").should( - "have.css", - "min-width", - "0px", - ); - }); - - it("valueChanged", () => { - let doenetML = ` -

-

-

-

$mi2.immediateValue

- - `; - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "false"); - cy.get(cesc2("#/mi2changed")).should("have.text", "false"); - cy.get(cesc2("#/mi3changed")).should("have.text", "false"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("type in first marks only first immediate value as changed"); - - cy.get(cesc2("#/mi1") + " textarea").type("y", { force: true }); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow").should("contain.text", "y"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "false"); - cy.get(cesc2("#/mi2changed")).should("have.text", "false"); - cy.get(cesc2("#/mi3changed")).should("have.text", "false"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("press enter in first marks only first value as changed"); - - cy.get(cesc2("#/mi1") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow").should("contain.text", "y"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "false"); - cy.get(cesc2("#/mi3changed")).should("have.text", "false"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("type in second marks only second immediate value as changed"); - - cy.get(cesc2("#/mi2") + " textarea").type("{end}{backspace}z", { - force: true, - }); - - cy.get(cesc2("#/mi2iva") + " .mjx-mrow").should("contain.text", "z"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "false"); - cy.get(cesc2("#/mi3changed")).should("have.text", "false"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("press enter in second marks only second value as changed"); - - cy.get(cesc2("#/mi2") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc2("#/mi2a") + " .mjx-mrow").should("contain.text", "z"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "true"); - cy.get(cesc2("#/mi3changed")).should("have.text", "false"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("type in third marks third immediate value as changed"); - - cy.get(cesc2("#/mi3") + " textarea").type("{end}{backspace}a", { - force: true, - }); - - cy.get(cesc2("#/mi3iva") + " .mjx-mrow").should("contain.text", "a"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "true"); - cy.get(cesc2("#/mi3changed")).should("have.text", "false"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("press enter in third marks third value as changed"); - - cy.get(cesc2("#/mi3") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc2("#/mi3a") + " .mjx-mrow").should("contain.text", "a"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "true"); - cy.get(cesc2("#/mi3changed")).should("have.text", "true"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("type in fourth marks fourth immediate value as changed"); - - cy.get(cesc2("#/mi4") + " textarea").type("{end}{backspace}b", { - force: true, - }); - - cy.get(cesc2("#/mi4iva") + " .mjx-mrow").should("contain.text", "b"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "b"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "true"); - cy.get(cesc2("#/mi3changed")).should("have.text", "true"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "true"); - - cy.log("press enter in fourth marks fourth value as changed"); - - cy.get(cesc2("#/mi4") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc2("#/mi4a") + " .mjx-mrow").should("contain.text", "b"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "b"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "b"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "b"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "a"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "b"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "true"); - cy.get(cesc2("#/mi3changed")).should("have.text", "true"); - cy.get(cesc2("#/mi4changed")).should("have.text", "true"); + .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "true"); + cy.wait(1500); // wait for debounce - cy.log("reload"); cy.reload(); cy.window().then(async (win) => { @@ -16834,418 +202,99 @@ describe("MathInput Tag Tests", function () { ); }); - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "false"); - cy.get(cesc2("#/mi2changed")).should("have.text", "false"); - cy.get(cesc2("#/mi3changed")).should("have.text", "false"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("type in third marks only third immediate value as changed"); - - cy.get(cesc2("#/mi3") + " textarea").type("y", { force: true }); - - cy.get(cesc2("#/mi3iva") + " .mjx-mrow").should("contain.text", "y"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "false"); - cy.get(cesc2("#/mi2changed")).should("have.text", "false"); - cy.get(cesc2("#/mi3changed")).should("have.text", "false"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log( - "press enter in third marks first and third value/immediateValue as changed", - ); - - cy.get(cesc2("#/mi3") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc2("#/mi3a") + " .mjx-mrow").should("contain.text", "y"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "false"); - cy.get(cesc2("#/mi3changed")).should("have.text", "true"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "false"); - - cy.log("type in fourth marks only fourth immediate value as changed"); - - cy.get(cesc2("#/mi4") + " textarea").type("{end}{backspace}z", { - force: true, - }); - - cy.get(cesc2("#/mi4iva") + " .mjx-mrow").should("contain.text", "z"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "false"); - cy.get(cesc2("#/mi3changed")).should("have.text", "true"); - cy.get(cesc2("#/mi4changed")).should("have.text", "false"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "true"); - - cy.log( - "press enter in fourth marks third and fourth value/immediateValue as changed", - ); - - cy.get(cesc2("#/mi4") + " textarea").type("{enter}", { force: true }); - - cy.get(cesc2("#/mi4a") + " .mjx-mrow").should("contain.text", "z"); - - cy.get(cesc2("#/mi1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi2iva") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc2("#/mi3iva") + " .mjx-mrow") + cy.get(cesc("#\\/pv") + " .mjx-mrow").should("contain.text", "1"); + cy.get(cesc("#\\/piv") + " .mjx-mrow") .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/mi4iva") + " .mjx-mrow") + .should("have.text", "1"); + cy.get(cesc("#\\/pv") + " .mjx-mrow") .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/mi1changed")).should("have.text", "true"); - cy.get(cesc2("#/mi2changed")).should("have.text", "true"); - cy.get(cesc2("#/mi3changed")).should("have.text", "true"); - cy.get(cesc2("#/mi4changed")).should("have.text", "true"); - - cy.get(cesc2("#/mi1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/mi4ivchanged")).should("have.text", "true"); + .should("have.text", "1"); }); - it("math input with label", () => { + it("minWidth attribute", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` -

-

+

Specify min width:

- `, +

Result:

+ `, }, "*", ); }); - cy.get(cesc2("#/mi1")).should("have.text", "Type something"); - cy.get(cesc2("#/mi2")).should("contain.text", "Hello"); - cy.get(cesc2("#/mi2") + " .mjx-mrow") - .eq(0) - .should("have.text", "ab"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mi1"].stateValues.label).eq( - "Type something", - ); - expect(stateVariables["/mi2"].stateValues.label).eq( - "Hello \\(\\frac{a}{b}\\)", - ); - }); - }); - - it("bound to fixed math", () => { - // Verify that fixed bug - // where deleting the mathinput contents wasn't restored on enter - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 -

$m - , - , -

-

- , - , -

- `, - }, - "*", - ); - }); + cy.get(cesc("#\\/mw") + " .mq-editable-field").should( + "have.css", + "min-width", + "50px", + ); - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); + cy.get(cesc("#\\/result") + " .mq-editable-field").should( + "have.css", + "min-width", + "0px", + ); - cy.get(cesc2("#/mi1v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi1iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi1rv")).should("have.text", "1"); - cy.get(cesc2(`#/mi1`) + ` .mq-editable-field`).should("have.text", "1"); + cy.get(cesc("#\\/mw") + " textarea").type( + "{end}{backspace}100{enter}", + { + force: true, + }, + ); + cy.get(cesc("#\\/result") + " .mq-editable-field").should( + "have.css", + "min-width", + "100px", + ); - cy.get(cesc2("#/mi2v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi2iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi2rv")).should("have.text", "1"); - cy.get(cesc2(`#/mi2`) + ` .mq-editable-field`).should("have.text", "1"); + cy.get(cesc("#\\/mw") + " textarea").type( + "{end}{backspace}{backspace}{backspace}{enter}", + { force: true }, + ); + cy.get(cesc("#\\/result") + " .mq-editable-field").should( + "have.css", + "min-width", + "0px", + ); - cy.log("Delete contents from mathinput 1"); - cy.get(cesc2("#/mi1") + " textarea").type("{end}{backspace}", { + cy.get(cesc("#\\/mw") + " textarea").type("{end}{backspace}40{enter}", { force: true, }); - cy.get(cesc2("#/mi1rv")).should("have.text", ""); - cy.get(cesc2("#/mi1v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi1iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2(`#/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.log("Contents of mathinput 1 restored on enter"); - cy.get(cesc2("#/mi1") + " textarea").type("{enter}", { force: true }); - cy.get(cesc2("#/mi1rv")).should("have.text", "1"); - cy.get(cesc2("#/mi1v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi1iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2(`#/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("1"); - }); - - cy.log("Add contents to mathinput 1"); - cy.get(cesc2("#/mi1") + " textarea").type("{end}2", { force: true }); - cy.get(cesc2("#/mi1rv")).should("have.text", "12"); - cy.get(cesc2("#/mi1v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi1iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "12"); - cy.get(cesc2(`#/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "12", - ); - }); - - cy.log("Contents of mathinput 1 restored on enter"); - cy.get(cesc2("#/mi1") + " textarea").type("{enter}", { force: true }); - cy.get(cesc2("#/mi1rv")).should("have.text", "1"); - cy.get(cesc2("#/mi1v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi1iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2(`#/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("1"); - }); + cy.get(cesc("#\\/result") + " .mq-editable-field").should( + "have.css", + "min-width", + "40px", + ); - cy.log("Delete contents from mathinput 2"); - cy.get(cesc2("#/mi2") + " textarea").type("{end}{backspace}", { + cy.get(cesc("#\\/mw") + " textarea").type("{end}x{enter}", { force: true, }); - cy.get(cesc2("#/mi2rv")).should("have.text", ""); - cy.get(cesc2("#/mi2v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi2iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2(`#/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - - cy.log("Contents of mathinput 2 restored on enter"); - cy.get(cesc2("#/mi2") + " textarea").type("{enter}", { force: true }); - cy.get(cesc2("#/mi2rv")).should("have.text", "1"); - cy.get(cesc2("#/mi2v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi2iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2(`#/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("1"); - }); + cy.get(cesc("#\\/result") + " .mq-editable-field").should( + "have.css", + "min-width", + "0px", + ); - cy.log("Add contents to mathinput 2"); - cy.get(cesc2("#/mi2") + " textarea").type("{end}2", { force: true }); - cy.get(cesc2("#/mi2rv")).should("have.text", "12"); - cy.get(cesc2("#/mi2v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi2iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "12"); - cy.get(cesc2(`#/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "12", - ); - }); + cy.get(cesc("#\\/mw") + " textarea").type( + "{end}{backspace}{backspace}7{enter}", + { force: true }, + ); + cy.get(cesc("#\\/result") + " .mq-editable-field").should( + "have.css", + "min-width", + "47px", + ); - cy.log("Contents of mathinput 2 restored on enter"); - cy.get(cesc2("#/mi2") + " textarea").type("{enter}", { force: true }); - cy.get(cesc2("#/mi2rv")).should("have.text", "1"); - cy.get(cesc2("#/mi2v") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/mi2iv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2(`#/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("1"); - }); + cy.get(cesc("#\\/mw") + " textarea").type( + "{end}{backspace}{backspace}-20{enter}", + { force: true }, + ); + cy.get(cesc("#\\/result") + " .mq-editable-field").should( + "have.css", + "min-width", + "0px", + ); }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/mathoperators.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/mathoperators.cy.js deleted file mode 100644 index 182329c54..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/mathoperators.cy.js +++ /dev/null @@ -1,14576 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; - -describe("Math Operator Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("sum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 6/2175-4 - 6/2175-4 - 6/2175-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+1"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+1"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62+17+1"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/withNumberSum")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z"); - }); - cy.get(cesc("#\\/varsSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+2y+z"); - }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(21); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eqls(["+", 3, 17, 1]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(21); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eqls(["+", 3, 17, 1]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(21); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eqls(["+", ["/", 6, 2], 17, 1]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/withNumberSum"].stateValues.value).eq( - 21, - ); - expect( - stateVariables["/withNumberSum"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberSum"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "+", - "x", - "x", - "y", - "x", - "y", - "z", - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.value).eqls([ - "+", - ["*", 3, "x"], - ["*", 2, "y"], - "z", - ]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq(21); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/varsb"].stateValues.value).eqls([ - "+", - "x", - "x", - "y", - "x", - "y", - "z", - ]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("sum with sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 - 17 - 5-4 - 3 - 6/2 - 3175-4 - 3 17 1 - 3 17 1 - 3 17 1 - 6/2 17 5-4 - 6/2 17 5-4 - 6/2 17 5-4 - $a$b$c - $a$b$c - $a$b$c - $a $b $c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - xx+yx+y+z - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+1"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numericAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62+17+5βˆ’4"); - }); - cy.get(cesc("#\\/numericAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numericAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersAsMacros")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+1"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersAsMacros2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/withNumberMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+1"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/withNumericMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62+17+1"); - }); - cy.get(cesc("#\\/withNumericMathMacroSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/withNumericMathMacroForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z"); - }); - cy.get(cesc("#\\/varsAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z"); - }); - cy.get(cesc("#\\/varsAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+2y+z"); - }); - cy.get(cesc("#\\/varsAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(21); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/numbersAsString"].stateValues.value).eq( - 21, - ); - expect( - stateVariables["/numbersAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsString"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .value, - ).eqls(["+", 3, 17, 1]); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numericAsString"].stateValues.value, - ).eqls(["+", ["/", 6, 2], 17, 5, -4]); - expect( - stateVariables["/numericAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsString"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .value, - ).eq(21); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .value, - ).eq(21); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/numbersAsMacros"].stateValues.value).eq( - 21, - ); - expect( - stateVariables["/numbersAsMacros"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .value, - ).eqls(["+", 3, 17, 1]); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersAsMacros2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.value, - ).eq(21); - expect( - stateVariables["/withNumberMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.value, - ).eqls(["+", 3, 17, 1]); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacro"].stateValues.value, - ).eqls(["+", ["/", 6, 2], 17, 1]); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .value, - ).eq(21); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "+", - "x", - "x", - "y", - "x", - "y", - "z", - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsAsString"].stateValues.value).eqls([ - "+", - "x", - "x", - "y", - "x", - "y", - "z", - ]); - expect( - stateVariables["/varsAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsAsString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsAsStringSimplify"].stateValues.value, - ).eqls(["+", ["*", 3, "x"], ["*", 2, "y"], "z"]); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .value, - ).eqls(NaN); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumber, - ).eq(false); - }); - }); - }); - - it("sum as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3 - 17 - 5-4 - - sum(3,17,5-4) - sum(3,17,5-4) - sum(3 17 5-4) - sum(3 17 5-4) - - sum(3,17,5-4) - - - sum(3,17,5-4) - - - sum(3175-4) - - - sum(3175-4) - - - sum($a,$b,$c) - - - sum($a,$b,$c) - - - sum($a$b$c) - - - sum($a$b$c) - - - sum($nums) - - - sum($nums) + sum($nums) - - - sum($nums) - - - sum($nums, $a, $b, $c) - - - sum($nums, $a, $b, $c) - - - sum($a, $b, $c, $nums) - - - sum($a, $b, $c, $nums) - - - sum($a, $b, $nums, $c) - - - sum($a, $b, $nums, $c) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numberStringProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3β‹…17β‹…5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("251"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3,17,1)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numberComponentsProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/numberComponentsProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3,17,1)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/macrosProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/macrosProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3,17,1)"); - }); - cy.get(cesc("#\\/groupPlusGroup")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3,17,1)+sum(3,17,1)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/groupPlus")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlusSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("42"); - }); - cy.get(cesc("#\\/groupPlus2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlus2Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("42"); - }); - cy.get(cesc("#\\/groupPlus3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sum(3,17,3,17,1,1)"); - }); - cy.get(cesc("#\\/groupPlus3Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("42"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "sum", - ["tuple", 3, 17, ["+", 5, -4]], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(21); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numberStringProduct"].stateValues.value, - ).eqls(["apply", "sum", ["+", ["*", 3, 17, 5], -4]]); - expect( - stateVariables["/numberStringProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .value, - ).eq(251); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "sum", ["tuple", 3, 17, 1]]); - expect( - await await stateVariables["/numberComponentsCommas"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .value, - ).eqls(["apply", "sum", ["*", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "sum", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(21); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/macrosProduct"].stateValues.value).eqls( - ["apply", "sum", ["*", 3, 17, 1]], - ); - expect( - stateVariables["/macrosProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/macrosProductSimplify"].stateValues.value, - ).eq(51); - expect( - stateVariables["/macrosProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "sum", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect( - stateVariables["/groupPlusGroup"].stateValues.value, - ).eqls([ - "+", - ["apply", "sum", ["tuple", 3, 17, 1]], - ["apply", "sum", ["tuple", 3, 17, 1]], - ]); - expect( - stateVariables["/groupPlusGroup"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - 21, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus"].stateValues.value).eqls([ - "apply", - "sum", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlusSimplify"].stateValues.value, - ).eq(42); - expect( - stateVariables["/groupPlusSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus2"].stateValues.value).eqls([ - "apply", - "sum", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.value, - ).eq(42); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus3"].stateValues.value).eqls([ - "apply", - "sum", - ["tuple", 3, 17, 3, 17, 1, 1], - ]); - expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.value, - ).eq(42); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("sum with lists", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 17 5-4 - 3 17 5-4 - 3 17 5-4 - 317 5-4 - 317 5-4 - 317 5-4 - 6/217 5-4 - 6/217 5-4 - 6/217 5-4 - 317 5-4 - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+1"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+1"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62+17+1"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/withNumberSum")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z"); - }); - cy.get(cesc("#\\/varsSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+2y+z"); - }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("21"); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(21); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eqls(["+", 3, 17, 1]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(21); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eqls(["+", 3, 17, 1]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(21); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eqls(["+", ["/", 6, 2], 17, 1]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(21); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/withNumberSum"].stateValues.value).eq( - 21, - ); - expect( - stateVariables["/withNumberSum"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberSum"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "+", - "x", - "x", - "y", - "x", - "y", - "z", - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.value).eqls([ - "+", - ["*", 3, "x"], - ["*", 2, "y"], - "z", - ]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq(21); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/varsb"].stateValues.value).eqls([ - "+", - "x", - "x", - "y", - "x", - "y", - "z", - ]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("product", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 6/2175-4 - 6/2175-4 - 6/2175-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3β‹…17β‹…1"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3β‹…17β‹…1"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(62)β‹…17β‹…1"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/withNumberProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(x+y)(x+y+z)"); - }); - cy.get(cesc("#\\/varsExpand")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3+2yx2+zx2+xy2+xyz"); - }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(x+y)(x+y+z)"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(51); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eqls(["*", 3, 17, 1]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(51); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eqls(["*", 3, 17, 1]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(51); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eqls(["*", ["/", 6, 2], 17, 1]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberProduct"].stateValues.value, - ).eq(51); - expect( - stateVariables["/withNumberProduct"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberProduct"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "*", - "x", - ["+", "x", "y"], - ["+", "x", "y", "z"], - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsExpand"].stateValues.value).eqls([ - "+", - ["^", "x", 3], - ["*", 2, "y", ["^", "x", 2]], - ["*", "z", ["^", "x", 2]], - ["*", "x", ["^", "y", 2]], - ["*", "x", "y", "z"], - ]); - expect( - stateVariables["/varsExpand"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsExpand"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq(51); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/varsb"].stateValues.value).eqls([ - "*", - "x", - ["+", "x", "y"], - ["+", "x", "y", "z"], - ]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("product with sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 - 17 - 5-4 - 3 - 6/2 - 3175-4 - 3 17 1 - 3 17 1 - 3 17 1 - 6/2 17 5-4 - 6/2 17 5-4 - 6/2 17 5-4 - $a$b$c - $a$b$c - $a$b$c - $a $b $c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - xx+yx+y+z - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3β‹…17β‹…1"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numericAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(62)β‹…17(5βˆ’4)"); - }); - cy.get(cesc("#\\/numericAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numericAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersAsMacros")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3β‹…17β‹…1"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersAsMacros2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/withNumberMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3β‹…17β‹…1"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/withNumericMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(62)β‹…17β‹…1"); - }); - cy.get(cesc("#\\/withNumericMathMacroSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/withNumericMathMacroForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(x+y)(x+y+z)"); - }); - cy.get(cesc("#\\/varsAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(x+y)(x+y+z)"); - }); - cy.get(cesc("#\\/varsAsStringExpand")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3+2yx2+zx2+xy2+xyz"); - }); - cy.get(cesc("#\\/varsAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(51); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/numbersAsString"].stateValues.value).eq( - 51, - ); - expect( - stateVariables["/numbersAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsString"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .value, - ).eqls(["*", 3, 17, 1]); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numericAsString"].stateValues.value, - ).eqls(["*", ["/", 6, 2], 17, ["+", 5, -4]]); - expect( - stateVariables["/numericAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsString"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .value, - ).eq(51); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .value, - ).eq(51); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/numbersAsMacros"].stateValues.value).eq( - 51, - ); - expect( - stateVariables["/numbersAsMacros"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .value, - ).eqls(["*", 3, 17, 1]); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersAsMacros2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.value, - ).eq(51); - expect( - stateVariables["/withNumberMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.value, - ).eqls(["*", 3, 17, 1]); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacro"].stateValues.value, - ).eqls(["*", ["/", 6, 2], 17, 1]); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .value, - ).eq(51); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "*", - "x", - ["+", "x", "y"], - ["+", "x", "y", "z"], - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsAsString"].stateValues.value).eqls([ - "*", - "x", - ["+", "x", "y"], - ["+", "x", "y", "z"], - ]); - expect( - stateVariables["/varsAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsAsString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsAsStringExpand"].stateValues.value, - ).eqls([ - "+", - ["^", "x", 3], - ["*", 2, "y", ["^", "x", 2]], - ["*", "z", ["^", "x", 2]], - ["*", "x", ["^", "y", 2]], - ["*", "x", "y", "z"], - ]); - expect( - stateVariables["/varsAsStringExpand"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/varsAsStringExpand"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .value, - ).eqls(NaN); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumber, - ).eq(false); - }); - }); - }); - - it("prod as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3 - 17 - 5-4 - - prod(3,17,5-4) - prod(3,17,5-4) - prod(3 17 5-4) - prod(3 17 5-4) - - prod(3,17,5-4) - - - prod(3,17,5-4) - - - prod(3175-4) - - - prod(3175-4) - - - prod($a,$b,$c) - - - prod($a,$b,$c) - - - prod($a$b$c) - - - prod($a$b$c) - - - prod($nums) - - - prod($nums) - - - prod($nums, $a, $b, $c) - - - prod($nums, $a, $b, $c) - - - prod($a, $b, $c, $nums) - - - prod($a, $b, $c, $nums) - - - prod($a, $b, $nums, $c) - - - prod($a, $b, $nums, $c) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numberStringProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3β‹…17β‹…5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("251"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3,17,1)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numberComponentsProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/numberComponentsProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3,17,1)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/macrosProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/macrosProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3,17,1)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/groupPlus")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlusSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2601"); - }); - cy.get(cesc("#\\/groupPlus2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlus2Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2601"); - }); - cy.get(cesc("#\\/groupPlus3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("prod(3,17,3,17,1,1)"); - }); - cy.get(cesc("#\\/groupPlus3Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2601"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "prod", - ["tuple", 3, 17, ["+", 5, -4]], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(51); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numberStringProduct"].stateValues.value, - ).eqls(["apply", "prod", ["+", ["*", 3, 17, 5], -4]]); - expect( - stateVariables["/numberStringProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .value, - ).eq(251); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "prod", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsCommas"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .value, - ).eqls(["apply", "prod", ["*", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "prod", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(51); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/macrosProduct"].stateValues.value).eqls( - ["apply", "prod", ["*", 3, 17, 1]], - ); - expect( - stateVariables["/macrosProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/macrosProductSimplify"].stateValues.value, - ).eq(51); - expect( - stateVariables["/macrosProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "prod", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - 51, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus"].stateValues.value).eqls([ - "apply", - "prod", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlusSimplify"].stateValues.value, - ).eq(2601); - expect( - stateVariables["/groupPlusSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus2"].stateValues.value).eqls([ - "apply", - "prod", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.value, - ).eq(2601); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus3"].stateValues.value).eqls([ - "apply", - "prod", - ["tuple", 3, 17, 3, 17, 1, 1], - ]); - expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.value, - ).eq(2601); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("product with lists", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 17 5-4 - 3 17 5-4 - 3 17 5-4 - 317 5-4 - 317 5-4 - 317 5-4 - 6/217 5-4 - 6/217 5-4 - 6/217 5-4 - 317 5-4 - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3β‹…17β‹…1"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3β‹…17β‹…1"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(62)β‹…17β‹…1"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/withNumberProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(x+y)(x+y+z)"); - }); - cy.get(cesc("#\\/varsExpand")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x3+2yx2+zx2+xy2+xyz"); - }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x(x+y)(x+y+z)"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(51); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eqls(["*", 3, 17, 1]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(51); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eqls(["*", 3, 17, 1]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(51); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eqls(["*", ["/", 6, 2], 17, 1]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberProduct"].stateValues.value, - ).eq(51); - expect( - stateVariables["/withNumberProduct"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberProduct"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "*", - "x", - ["+", "x", "y"], - ["+", "x", "y", "z"], - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsExpand"].stateValues.value).eqls([ - "+", - ["^", "x", 3], - ["*", 2, "y", ["^", "x", 2]], - ["*", "z", ["^", "x", 2]], - ["*", "x", ["^", "y", 2]], - ["*", "x", "y", "z"], - ]); - expect( - stateVariables["/varsExpand"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsExpand"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq(51); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/varsb"].stateValues.value).eqls([ - "*", - "x", - ["+", "x", "y"], - ["+", "x", "y", "z"], - ]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("clamp number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 55.3 - -55.3 - 0.3 - - 55.3 - -55.3 - 12 - - 55.3 - -55.3 - 12 - - x+y - x+y - - 4 - - 12$a - -12$a - 3$a - - $_clampnumber1{name="clampnumber1b"} - $_clampnumber5{name="clampnumber5b"} - $_clampnumber9{name="clampnumber9b"} - $_clampnumber14{name="clampnumber14b"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/_clampnumber1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/_clampnumber2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/_clampnumber3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0.3"); - }); - cy.get(cesc("#\\/_clampnumber4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("40"); - }); - cy.get(cesc("#\\/_clampnumber5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10"); - }); - cy.get(cesc("#\\/_clampnumber6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/_clampnumber7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("40"); - }); - cy.get(cesc("#\\/_clampnumber8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10"); - }); - cy.get(cesc("#\\/_clampnumber9")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/_clampnumber10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/_clampnumber11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/_clampnumber12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("40"); - }); - cy.get(cesc("#\\/_clampnumber13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10"); - }); - cy.get(cesc("#\\/_clampnumber14")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/clampnumber1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/clampnumber5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10"); - }); - cy.get(cesc("#\\/clampnumber9b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/clampnumber14b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - - cy.window().then(async (win) => { - expect(stateVariables["/_clampnumber1"].stateValues.value).eq( - 1, - ); - expect(stateVariables["/_clampnumber2"].stateValues.value).eq( - 0, - ); - expect(stateVariables["/_clampnumber3"].stateValues.value).eq( - 0.3, - ); - expect(stateVariables["/_clampnumber4"].stateValues.value).eq( - 40, - ); - expect(stateVariables["/_clampnumber5"].stateValues.value).eq( - 10, - ); - expect(stateVariables["/_clampnumber6"].stateValues.value).eq( - 12, - ); - expect(stateVariables["/_clampnumber7"].stateValues.value).eq( - 40, - ); - expect(stateVariables["/_clampnumber8"].stateValues.value).eq( - 10, - ); - expect(stateVariables["/_clampnumber9"].stateValues.value).eq( - 12, - ); - expect( - stateVariables["/_clampnumber10"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/_clampnumber11"].stateValues.value, - ).eqls(NaN); - expect(stateVariables["/_clampnumber12"].stateValues.value).eq( - 40, - ); - expect(stateVariables["/_clampnumber13"].stateValues.value).eq( - 10, - ); - expect(stateVariables["/_clampnumber14"].stateValues.value).eq( - 12, - ); - expect(stateVariables["/clampnumber1b"].stateValues.value).eq( - 1, - ); - expect(stateVariables["/clampnumber5b"].stateValues.value).eq( - 10, - ); - expect(stateVariables["/clampnumber9b"].stateValues.value).eq( - 12, - ); - expect(stateVariables["/clampnumber14b"].stateValues.value).eq( - 12, - ); - expect( - stateVariables["/_clampnumber1"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber3"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber4"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber5"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber6"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber7"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber8"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber9"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber10"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber11"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber12"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber13"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber14"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/clampnumber1b"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/clampnumber5b"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/clampnumber9b"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/clampnumber14b"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_clampnumber1"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber3"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber4"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber5"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber6"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber7"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber8"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber9"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber10"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/_clampnumber11"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/_clampnumber12"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber13"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/_clampnumber14"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/clampnumber1b"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/clampnumber5b"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/clampnumber9b"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/clampnumber14b"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("wrap number periodic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 55.3 - -55.3 - 0.3 - - 55.3 - -55.3 - 12 - - 55.3 - -55.3 - 12 - - x+y - x+y - - 4 - - 12$a - -12$a - 3$a - - $_wrapnumberperiodic1{name="wrapnumberperiodic1b"} - $_wrapnumberperiodic5{name="wrapnumberperiodic5b"} - $_wrapnumberperiodic9{name="wrapnumberperiodic9b"} - $_wrapnumberperiodic14{name="wrapnumberperiodic14b"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/_wrapnumberperiodic1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0.3"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0.7"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0.3"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25.3"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("34.7"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25.3"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("34.7"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic9")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("18"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/_wrapnumberperiodic14")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/wrapnumberperiodic1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0.3"); - }); - cy.get(cesc("#\\/wrapnumberperiodic5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("34.7"); - }); - cy.get(cesc("#\\/wrapnumberperiodic9b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - cy.get(cesc("#\\/wrapnumberperiodic14b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12"); - }); - - cy.window().then(async (win) => { - expect( - stateVariables["/_wrapnumberperiodic1"].stateValues.value, - ).closeTo(0.3, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic2"].stateValues.value, - ).closeTo(0.7, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic3"].stateValues.value, - ).closeTo(0.3, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic4"].stateValues.value, - ).closeTo(25.3, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic5"].stateValues.value, - ).closeTo(34.7, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic6"].stateValues.value, - ).closeTo(12, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic7"].stateValues.value, - ).closeTo(25.3, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic8"].stateValues.value, - ).closeTo(34.7, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic9"].stateValues.value, - ).closeTo(12, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic10"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/_wrapnumberperiodic11"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/_wrapnumberperiodic12"].stateValues.value, - ).closeTo(18, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic13"].stateValues.value, - ).closeTo(12, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic14"].stateValues.value, - ).closeTo(12, 1e-12); - expect( - stateVariables["/wrapnumberperiodic1b"].stateValues.value, - ).closeTo(0.3, 1e-12); - expect( - stateVariables["/wrapnumberperiodic5b"].stateValues.value, - ).closeTo(34.7, 1e-12); - expect( - stateVariables["/wrapnumberperiodic9b"].stateValues.value, - ).closeTo(12, 1e-12); - expect( - stateVariables["/wrapnumberperiodic14b"].stateValues.value, - ).closeTo(12, 1e-12); - expect( - stateVariables["/_wrapnumberperiodic1"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic3"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic4"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic5"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic6"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic7"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic8"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic9"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic10"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic11"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic12"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic13"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic14"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/wrapnumberperiodic1b"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/wrapnumberperiodic5b"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/wrapnumberperiodic9b"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/wrapnumberperiodic14b"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic1"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic2"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic3"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic4"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic5"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic6"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic7"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic8"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic9"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic10"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/_wrapnumberperiodic11"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/_wrapnumberperiodic12"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic13"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/_wrapnumberperiodic14"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/wrapnumberperiodic1b"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/wrapnumberperiodic5b"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/wrapnumberperiodic9b"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/wrapnumberperiodic14b"].stateValues - .isNumber, - ).eq(true); - }); - }); - }); - - it("clamp and wrap number updatable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (6,7) - - ( - $_point1.x - , - - $_point1.y - - ) - - ($_point2.y, $_point2.x) - - - $_graph1{name="g2"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let clamp = (x) => Math.min(5, Math.max(-2, x)); - let wrap = (x) => -2 + me.math.mod(x + 2, 7); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x = 6, - y = 7; - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(x); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(y); - expect(stateVariables["/_point2"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point2"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[0]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[1]).eq(clamp(x)); - - let g2children = stateVariables["/g2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect((await g2children[0].stateValues.xs)[0]).eq(x); - expect((await g2children[0].stateValues.xs)[1]).eq(y); - expect((await g2children[1].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[1].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[0]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[1]).eq(clamp(x)); - }); - - cy.log("move point 1"); - cy.window().then(async (win) => { - let x = -5, - y = 0; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x, y }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(x); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(y); - expect(stateVariables["/_point2"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point2"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[0]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[1]).eq(clamp(x)); - - let g2children = stateVariables["/g2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect((await g2children[0].stateValues.xs)[0]).eq(x); - expect((await g2children[0].stateValues.xs)[1]).eq(y); - expect((await g2children[1].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[1].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[0]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[1]).eq(clamp(x)); - }); - - cy.log("move point 2"); - cy.window().then(async (win) => { - let x = 9, - y = -3; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x, y }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point2"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point2"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[0]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[1]).eq(clamp(x)); - - let g2children = stateVariables["/g2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect((await g2children[0].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[0].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[1].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[1].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[0]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[1]).eq(clamp(x)); - }); - - cy.log("move point 3"); - cy.window().then(async (win) => { - let x = -4, - y = 8; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point3", - args: { x: y, y: x }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point2"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point2"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[0]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[1]).eq(clamp(x)); - - let g2children = stateVariables["/g2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect((await g2children[0].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[0].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[1].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[1].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[0]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[1]).eq(clamp(x)); - }); - - cy.log("move point 4"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x = 10, - y = -10; - - await win.callAction1({ - actionName: "movePoint", - componentName: - stateVariables["/g2"].activeChildren[0].componentName, - args: { x, y }, - }); - stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(x); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(y); - expect(stateVariables["/_point2"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point2"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[0]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[1]).eq(clamp(x)); - - let g2children = stateVariables["/g2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect((await g2children[0].stateValues.xs)[0]).eq(x); - expect((await g2children[0].stateValues.xs)[1]).eq(y); - expect((await g2children[1].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[1].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[0]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[1]).eq(clamp(x)); - }); - - cy.log("move point 5"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x = 11, - y = -13; - - await win.callAction1({ - actionName: "movePoint", - componentName: - stateVariables["/g2"].activeChildren[1].componentName, - args: { x, y }, - }); - stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point2"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point2"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[0]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[1]).eq(clamp(x)); - - let g2children = stateVariables["/g2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect((await g2children[0].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[0].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[1].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[1].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[0]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[1]).eq(clamp(x)); - }); - - cy.log("move point 6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x = -3, - y = 12; - - await win.callAction1({ - actionName: "movePoint", - componentName: - stateVariables["/g2"].activeChildren[2].componentName, - args: { x: y, y: x }, - }); - - stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point2"].stateValues.xs[0]).eq(clamp(x)); - expect(stateVariables["/_point2"].stateValues.xs[1]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[0]).eq(wrap(y)); - expect(stateVariables["/_point3"].stateValues.xs[1]).eq(clamp(x)); - - let g2children = stateVariables["/g2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect((await g2children[0].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[0].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[1].stateValues.xs)[0]).eq(clamp(x)); - expect((await g2children[1].stateValues.xs)[1]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[0]).eq(wrap(y)); - expect((await g2children[2].stateValues.xs)[1]).eq(clamp(x)); - }); - }); - - it("round", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 55.3252326 - log(31) - 0.5 - - 55.3252326 - log(31) - 0.5555 - - 55.3252326 - log(31) - 0.555555 - - sin(55.3252326 x) - log(31) exp(3) sin(2) - - exp(20) pi - - $_round1{name="round1b"} - $_round5{name="round5b"} - $_round11{name="round11b"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/_round1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("55"); - }); - cy.get(cesc("#\\/_round2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/_round3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/_round4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("55.3"); - }); - cy.get(cesc("#\\/_round5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3.43"); - }); - cy.get(cesc("#\\/_round6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0.556"); - }); - cy.get(cesc("#\\/_round7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("55.3"); - }); - cy.get(cesc("#\\/_round8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3.434"); - }); - cy.get(cesc("#\\/_round9")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0.55556"); - }); - cy.get(cesc("#\\/_round10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(55.3x)"); - }); - cy.get(cesc("#\\/_round11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.7"); - }); - cy.get(cesc("#\\/_round12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1524000000"); - }); - cy.get(cesc("#\\/round1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("55"); - }); - cy.get(cesc("#\\/round5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3.43"); - }); - cy.get(cesc("#\\/round11b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62.7"); - }); - - cy.window().then(async (win) => { - expect(stateVariables["/_round1"].stateValues.value).eq(55); - expect(stateVariables["/_round2"].stateValues.value).eq(3); - expect(stateVariables["/_round3"].stateValues.value).eq(1); - expect(stateVariables["/_round4"].stateValues.value).eq(55.3); - expect(stateVariables["/_round5"].stateValues.value).eq(3.43); - expect(stateVariables["/_round6"].stateValues.value).eq(0.556); - expect(stateVariables["/_round7"].stateValues.value).eq(55.3); - expect(stateVariables["/_round8"].stateValues.value).eq(3.434); - expect(stateVariables["/_round9"].stateValues.value).eq( - 0.55556, - ); - expect(stateVariables["/_round10"].stateValues.value).eqls([ - "apply", - "sin", - ["*", 55.3, "x"], - ]); - expect(stateVariables["/_round11"].stateValues.value).eq(62.7); - expect(stateVariables["/_round12"].stateValues.value).eq( - 1524000000, - ); - expect(stateVariables["/round1b"].stateValues.value).eq(55); - expect(stateVariables["/round5b"].stateValues.value).eq(3.43); - expect(stateVariables["/round11b"].stateValues.value).eq(62.7); - }); - }); - }); - - it("round ignores display rounding of math children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 55.3252326 - 55.3252326 - 55.3252326 - 55.3252326 - - 55.3252326 - 55.3252326 - 55.3252326 - 55.3252326 - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc2("#/_round1") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/_round2") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/_round3") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - cy.get(cesc2("#/_round4") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - - cy.get(cesc2("#/_round5") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/_round6") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/_round7") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - cy.get(cesc2("#/_round8") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - - cy.get(cesc2("#/r1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/r2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/r3a") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - cy.get(cesc2("#/r4a") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - - cy.get(cesc2("#/r5a") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/r6a") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/r7a") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - cy.get(cesc2("#/r8a") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - - cy.get(cesc2("#/r1b") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/r2b") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/r3b") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - cy.get(cesc2("#/r4b") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - - cy.get(cesc2("#/r5b") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/r6b") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.3252"); - cy.get(cesc2("#/r7b") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - cy.get(cesc2("#/r8b") + " .mjx-mrow") - .eq(0) - .should("have.text", "55.325233"); - }); - - it("convert set to list", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - -

a

-

{1,2,3,2,1}

-

(1,2,3,2,1)

-

1,2,3,2,1

- -

$_math1

-

$_math2

-

$_math3

- -

$_convertsettolist1{name="r1"}

-

$_convertsettolist2{name="r2"}

-

$_convertsettolist3{name="r3"}

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("{1,2,3,2,1}"); - }); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,3,2,1)"); - }); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2,3,2,1"); - }); - cy.get(cesc("#\\/_convertsettolist1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2,3"); - }); - cy.get(cesc("#\\/_convertsettolist2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,3,2,1)"); - }); - cy.get(cesc("#\\/_convertsettolist3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2,3,2,1"); - }); - cy.get(cesc("#\\/r1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2,3"); - }); - cy.get(cesc("#\\/r2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,3,2,1)"); - }); - cy.get(cesc("#\\/r3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1,2,3,2,1"); - }); - - cy.window().then(async (win) => { - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "set", - 1, - 2, - 3, - 2, - 1, - ]); - expect(stateVariables["/_math2"].stateValues.value).eqls([ - "tuple", - 1, - 2, - 3, - 2, - 1, - ]); - expect(stateVariables["/_math3"].stateValues.value).eqls([ - "list", - 1, - 2, - 3, - 2, - 1, - ]); - expect( - stateVariables["/_convertsettolist1"].stateValues.value, - ).eqls(["list", 1, 2, 3]); - expect( - stateVariables["/_convertsettolist2"].stateValues.value, - ).eqls(["tuple", 1, 2, 3, 2, 1]); - expect( - stateVariables["/_convertsettolist3"].stateValues.value, - ).eqls(["list", 1, 2, 3, 2, 1]); - expect(stateVariables["/r1"].stateValues.value).eqls([ - "list", - 1, - 2, - 3, - ]); - expect(stateVariables["/r2"].stateValues.value).eqls([ - "tuple", - 1, - 2, - 3, - 2, - 1, - ]); - expect(stateVariables["/r3"].stateValues.value).eqls([ - "list", - 1, - 2, - 3, - 2, - 1, - ]); - expect( - stateVariables["/_convertsettolist1"].stateValues.unordered, - ).eq(true); - expect( - stateVariables["/_convertsettolist2"].stateValues.unordered, - ).eq(true); - expect( - stateVariables["/_convertsettolist3"].stateValues.unordered, - ).eq(true); - expect(stateVariables["/r1"].stateValues.unordered).eq(true); - expect(stateVariables["/r2"].stateValues.unordered).eq(true); - expect(stateVariables["/r3"].stateValues.unordered).eq(true); - }); - }); - }); - - it("convert set to list, initially unresolved", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - -

a

- -

7 - -

- -

{$m,$n,$p,$m}

-

$_convertsettolist1{name="csl2"}

- -

$n3{name="n2"} - $num1{name="n"} - $n2+$num2 - $n3+$num3 - $num3{name="n3"} - 1

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let p = await stateVariables["/p"].stateValues.value; - expect( - stateVariables["/_convertsettolist1"].stateValues.value, - ).eqls(["list", 7, 3, p]); - expect(stateVariables["/csl2"].stateValues.value).eqls([ - "list", - 7, - 3, - p, - ]); - expect( - stateVariables["/_convertsettolist1"].stateValues.unordered, - ).eq(true); - expect(stateVariables["/csl2"].stateValues.unordered).eq(true); - }); - }); - - it("floor and ceil", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 55.3252326 - log(31) - - $_floor1/$_ceil1 - $_ceil1/$_floor1 - -

Allow for slight roundoff error: - 3.999999999999999 - -6999.999999999999 -

- - $_floor2{name="f2a"} - $_ceil2{name="c2a"} - - 2.1x - -3.2y - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/_floor1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("55"); - }); - cy.get(cesc("#\\/_ceil1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/_floor2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("13"); - }); - cy.get(cesc("#\\/_ceil2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/_floor3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/_ceil3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("βˆ’7000"); - }); - cy.get(cesc("#\\/f2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("13"); - }); - cy.get(cesc("#\\/c2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/_floor4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("⌊2.1xβŒ‹"); - }); - cy.get(cesc("#\\/_ceil4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("βŒˆβˆ’3.2yβŒ‰"); - }); - - cy.window().then(async (win) => { - expect(stateVariables["/_floor1"].stateValues.value).eq(55); - expect(stateVariables["/_ceil1"].stateValues.value).eq(4); - expect(stateVariables["/_floor2"].stateValues.value).eq(13); - expect(stateVariables["/_ceil2"].stateValues.value).eq(1); - expect(stateVariables["/_floor3"].stateValues.value).eq(4); - expect(stateVariables["/_ceil3"].stateValues.value).eq(-7000); - expect(stateVariables["/f2a"].stateValues.value).eq(13); - expect(stateVariables["/c2a"].stateValues.value).eq(1); - expect(stateVariables["/_floor4"].stateValues.value).eqls([ - "apply", - "floor", - ["*", 2.1, "x"], - ]); - expect(stateVariables["/_ceil4"].stateValues.value).eqls([ - "apply", - "ceil", - ["-", ["*", 3.2, "y"]], - ]); - }); - }); - }); - - it("floor and ceil as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - \\lfloor 55.3252326 \\rfloor - floor(55.3252326) - - - \\lceil \\log(31.1) \\rceil - ceil(log(31.1)) - - - - \\lfloor $floor1/$ceil1 \\rfloor - floor($floor1/$ceil1) - \\lceil $ceil1/$floor1 \\rceil - ceil($ceil1/$floor1) - -

Allow for slight roundoff error: - \\lfloor 3.999999999999999 \\rfloor - floor 3.999999999999999 - \\lceil -6999.999999999999 \\rceil - ceil -6999.999999999999 -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/floor1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("⌊55.3252326βŒ‹"); - }); - cy.get(cesc("#\\/floor2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("⌊55.3252326βŒ‹"); - }); - cy.get(cesc("#\\/floor1simp")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("55"); - }); - cy.get(cesc("#\\/floor2simp")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("55"); - }); - cy.get(cesc("#\\/ceil1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("⌈log(31.1)βŒ‰"); - }); - cy.get(cesc("#\\/ceil2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("⌈log(31.1)βŒ‰"); - }); - cy.get(cesc("#\\/ceil1simp")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/ceil2simp")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/floor3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("13"); - }); - cy.get(cesc("#\\/floor4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("13"); - }); - cy.get(cesc("#\\/ceil3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/ceil4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/floor5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/floor6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/ceil5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("βˆ’7000"); - }); - cy.get(cesc("#\\/ceil6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("βˆ’7000"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/floor1"].stateValues.value).eqls([ - "apply", - "floor", - 55.3252326, - ]); - expect(stateVariables["/floor2"].stateValues.value).eqls([ - "apply", - "floor", - 55.3252326, - ]); - expect(stateVariables["/floor1simp"].stateValues.value).eq(55); - expect(stateVariables["/floor2simp"].stateValues.value).eq(55); - expect(stateVariables["/ceil1"].stateValues.value).eqls([ - "apply", - "ceil", - ["apply", "log", 31.1], - ]); - expect(stateVariables["/ceil2"].stateValues.value).eqls([ - "apply", - "ceil", - ["apply", "log", 31.1], - ]); - expect(stateVariables["/ceil1simp"].stateValues.value).eq(4); - expect(stateVariables["/ceil2simp"].stateValues.value).eq(4); - expect(stateVariables["/floor3"].stateValues.value).eq(13); - expect(stateVariables["/floor4"].stateValues.value).eq(13); - expect(stateVariables["/ceil3"].stateValues.value).eq(1); - expect(stateVariables["/ceil4"].stateValues.value).eq(1); - expect(stateVariables["/floor5"].stateValues.value).eq(4); - expect(stateVariables["/floor6"].stateValues.value).eq(4); - expect(stateVariables["/ceil5"].stateValues.value).eq(-7000); - expect(stateVariables["/ceil6"].stateValues.value).eq(-7000); - }); - }); - - it("abs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -5.3 - -x - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_abs1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5.3"); - }); - cy.get(cesc("#\\/_abs2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("|βˆ’x|"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_abs1"].stateValues.value).eq(5.3); - expect(stateVariables["/_abs2"].stateValues.value).eqls([ - "apply", - "abs", - ["-", "x"], - ]); - }); - }); - - it("invert abs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -9 - - $a2.value{assignNames="a3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("9"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a1"].stateValues.value).eq(9); - expect(stateVariables["/a2"].stateValues.value).eq(9); - expect(stateVariables["/a3"].stateValues.value).eq(9); - }); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}-3{enter}", { - force: true, - }); - cy.get(cesc("#\\/a3")).should("contain.text", "0"); - - cy.get(cesc("#\\/a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("0"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a1"].stateValues.value).eq(0); - expect(stateVariables["/a2"].stateValues.value).eq(0); - expect(stateVariables["/a3"].stateValues.value).eq(0); - }); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}7{enter}", { - force: true, - }); - cy.get(cesc("#\\/a3")).should("contain.text", "7"); - - cy.get(cesc("#\\/a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("7"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a1"].stateValues.value).eq(7); - expect(stateVariables["/a2"].stateValues.value).eq(7); - expect(stateVariables["/a3"].stateValues.value).eq(7); - }); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}x{enter}", { - force: true, - }); - cy.get(cesc("#\\/a3")).should("contain.text", "|x|"); - - cy.get(cesc("#\\/a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("|x|"); - }); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "|x|", - ); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("|x|"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a1"].stateValues.value).eqls([ - "apply", - "abs", - "x", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "abs", - "x", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "abs", - "x", - ]); - }); - - cy.get(cesc("#\\/a2") + " textarea").type( - "{end}{leftArrow}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/a3")).should("contain.text", "|y|"); - - cy.get(cesc("#\\/a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("|y|"); - }); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "|y|", - ); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("|y|"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a1"].stateValues.value).eqls([ - "apply", - "abs", - "y", - ]); - expect(stateVariables["/a2"].stateValues.value).eqls([ - "apply", - "abs", - "y", - ]); - expect(stateVariables["/a3"].stateValues.value).eqls([ - "apply", - "abs", - "y", - ]); - }); - }); - - it("floor, ceil, round and abs updatable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (6.1,7.6) - - ( - - $_point1.x - , - - $_point1.y - - ) - - ($_point2.y, $_point1.x) - - - $_graph1{name="g2"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let g2ChildrenNames; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - g2ChildrenNames = stateVariables["/g2"].activeChildren.map( - (x) => x.componentName, - ); - }); - - let checkPoints = async function (x, y) { - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(x); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(y); - expect(stateVariables["/_point2"].stateValues.xs[0]).eq( - Math.floor(x), - ); - expect(stateVariables["/_point2"].stateValues.xs[1]).eq( - Math.ceil(y), - ); - expect(stateVariables["/_point3"].stateValues.xs[0]).eq( - Math.abs(Math.ceil(y)), - ); - expect(stateVariables["/_point3"].stateValues.xs[1]).eq( - Math.round(x), - ); - - let g2Children = g2ChildrenNames.map((x) => stateVariables[x]); - expect((await g2Children[0].stateValues.xs)[0]).eq(x); - expect((await g2Children[0].stateValues.xs)[1]).eq(y); - expect((await g2Children[1].stateValues.xs)[0]).eq( - Math.floor(x), - ); - expect((await g2Children[1].stateValues.xs)[1]).eq( - Math.ceil(y), - ); - expect((await g2Children[2].stateValues.xs)[0]).eq( - Math.abs(Math.ceil(y)), - ); - expect((await g2Children[2].stateValues.xs)[1]).eq( - Math.round(x), - ); - }); - }; - - checkPoints(6.1, 7.6); - - cy.log("move point 1, positive y"); - cy.window().then(async (win) => { - let x = -5.1, - y = 0.3; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x, y }, - }); - checkPoints(x, y); - }); - - cy.log("move point 1, negative y"); - cy.window().then(async (win) => { - let x = -7.9, - y = -5.8; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x, y }, - }); - checkPoints(x, y); - }); - - cy.log("move point 2, positive y"); - cy.window().then(async (win) => { - let x = 3.4, - y = 8.6; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x, y }, - }); - checkPoints(x, y); - }); - - cy.log("move point 2, negative y"); - cy.window().then(async (win) => { - let x = 7.7, - y = -4.4; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x, y }, - }); - checkPoints(x, y); - }); - - cy.log("move point 3, positive x"); - cy.window().then(async (win) => { - let x = 9.4, - y = -1.3; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point3", - args: { x, y }, - }); - checkPoints(y, x); - }); - - cy.log("move point 3, negative x"); - cy.window().then(async (win) => { - let x = -8.9, - y = -4.6; - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point3", - args: { x, y }, - }); - checkPoints(y, 0); - }); - - cy.log("move point 4, positive y"); - cy.window().then(async (win) => { - let x = 6.8, - y = 3.7; - - await win.callAction1({ - actionName: "movePoint", - componentName: g2ChildrenNames[0], - args: { x, y }, - }); - checkPoints(x, y); - }); - - cy.log("move point 4, negative y"); - cy.window().then(async (win) => { - let x = 1.2, - y = -1.4; - await win.callAction1({ - actionName: "movePoint", - componentName: g2ChildrenNames[0], - args: { x, y }, - }); - checkPoints(x, y); - }); - - cy.log("move point 5, positive y"); - cy.window().then(async (win) => { - let x = -6.6, - y = 3.2; - await win.callAction1({ - actionName: "movePoint", - componentName: g2ChildrenNames[1], - args: { x, y }, - }); - checkPoints(x, y); - }); - - cy.log("move point 5, negative y"); - cy.window().then(async (win) => { - let x = -4.3, - y = -8.9; - await win.callAction1({ - actionName: "movePoint", - componentName: g2ChildrenNames[1], - args: { x, y }, - }); - checkPoints(x, y); - }); - - cy.log("move point 6, positive x"); - cy.window().then(async (win) => { - let x = 6.4, - y = 2.3; - await win.callAction1({ - actionName: "movePoint", - componentName: g2ChildrenNames[2], - args: { x, y }, - }); - checkPoints(y, x); - }); - - cy.log("move point 6, negative x"); - cy.window().then(async (win) => { - let x = -5.6, - y = 7.8; - await win.callAction1({ - actionName: "movePoint", - componentName: g2ChildrenNames[2], - args: { x, y }, - }); - checkPoints(y, 0); - }); - }); - - it("sign", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -5.3 - 63 - 0 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_sign1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("βˆ’1"); - }); - cy.get(cesc("#\\/_sign2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/_sign3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_sign1"].stateValues.value).eq(-1); - expect(stateVariables["/_sign2"].stateValues.value).eq(1); - expect(stateVariables["/_sign3"].stateValues.value).eq(0); - }); - }); - - it("mean", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 6/2175-4 - 6/2175-4 - 6/2175-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+13"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+13"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62+17+13"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/withNumberMean")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z3"); - }); - cy.get(cesc("#\\/varsSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+2y+z3"); - }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z3"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(7); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eqls(["/", ["+", 3, 17, 1], 3]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(7); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(7); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eqls(["/", ["+", 3, 17, 1], 3]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(7); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eqls(["/", ["+", ["/", 6, 2], 17, 1], 3]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(7); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(7); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/withNumberMean"].stateValues.value).eq( - 6, - ); - expect( - stateVariables["/withNumberMean"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMean"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "/", - ["+", "x", "x", "y", "x", "y", "z"], - 3, - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.value).eqls([ - "/", - ["+", ["*", 3, "x"], ["*", 2, "y"], "z"], - 3, - ]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq(7); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/varsb"].stateValues.value).eqls([ - "/", - ["+", "x", "x", "y", "x", "y", "z"], - 3, - ]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("mean with sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 - 17 - 5-4 - 3 - 6/2 - 3175-4 - 3 17 1 - 3 17 1 - 3 17 1 - 6/2 17 5-4 - 6/2 17 5-4 - 6/2 17 5-4 - $a$b$c - $a$b$c - $a$b$c - $a $b $c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - xx+yx+y+z - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+13"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numericAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62+17+5βˆ’43"); - }); - cy.get(cesc("#\\/numericAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numericAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersAsMacros")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+13"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numbersAsMacros2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/withNumberMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3+17+13"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/withNumericMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("62+17+13"); - }); - cy.get(cesc("#\\/withNumericMathMacroSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/withNumericMathMacroForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z3"); - }); - cy.get(cesc("#\\/varsAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+x+y+x+y+z3"); - }); - cy.get(cesc("#\\/varsAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x+2y+z3"); - }); - cy.get(cesc("#\\/varsAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(7); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/numbersAsString"].stateValues.value).eq( - 7, - ); - expect( - stateVariables["/numbersAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsString"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .value, - ).eqls(["/", ["+", 3, 17, 1], 3]); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.value, - ).eq(7); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numericAsString"].stateValues.value, - ).eqls(["/", ["+", ["/", 6, 2], 17, 5, -4], 3]); - expect( - stateVariables["/numericAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsString"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .value, - ).eq(7); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .value, - ).eq(7); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/numbersAsMacros"].stateValues.value).eq( - 7, - ); - expect( - stateVariables["/numbersAsMacros"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .value, - ).eqls(["/", ["+", 3, 17, 1], 3]); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.value, - ).eq(7); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.value, - ).eq(7); - expect( - stateVariables["/numbersAsMacros2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.value, - ).eq(7); - expect( - stateVariables["/withNumberMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.value, - ).eqls(["/", ["+", 3, 17, 1], 3]); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.value, - ).eq(7); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacro"].stateValues.value, - ).eqls(["/", ["+", ["/", 6, 2], 17, 1], 3]); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .value, - ).eq(7); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.value, - ).eq(7); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "/", - ["+", "x", "x", "y", "x", "y", "z"], - 3, - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsAsString"].stateValues.value).eqls([ - "/", - ["+", "x", "x", "y", "x", "y", "z"], - 3, - ]); - expect( - stateVariables["/varsAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsAsString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/varsAsStringSimplify"].stateValues.value, - ).eqls(["/", ["+", ["*", 3, "x"], ["*", 2, "y"], "z"], 3]); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .value, - ).eqls(NaN); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumber, - ).eq(false); - }); - }); - }); - - it("mean as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3 - 17 - 5-4 - - mean(3,17,5-4) - mean(3,17,5-4) - mean(3 17 5-4) - mean(3 17 5-4) - - mean(3,17,5-4) - - - mean(3,17,5-4) - - - mean(3175-4) - - - mean(3175-4) - - - mean($a,$b,$c) - - - mean($a,$b,$c) - - - mean($a$b$c) - - - mean($a$b$c) - - - mean($nums) - - - mean($nums) - - - mean($nums, $a, $b, $c) - - - mean($nums, $a, $b, $c) - - - mean($a, $b, $c, $nums) - - - mean($a, $b, $c, $nums) - - - mean($a, $b, $nums, $c) - - - mean($a, $b, $nums, $c) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numberStringProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3β‹…17β‹…5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("251"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3,17,1)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/numberComponentsProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/numberComponentsProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3,17,1)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/macrosProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/macrosProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3,17,1)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/groupPlus")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlusSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/groupPlus2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlus2Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(cesc("#\\/groupPlus3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mean(3,17,3,17,1,1)"); - }); - cy.get(cesc("#\\/groupPlus3Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "mean", - ["tuple", 3, 17, ["+", 5, -4]], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(7); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numberStringProduct"].stateValues.value, - ).eqls(["apply", "mean", ["+", ["*", 3, 17, 5], -4]]); - expect( - stateVariables["/numberStringProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .value, - ).eq(251); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "mean", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsCommas"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(7); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .value, - ).eqls(["apply", "mean", ["*", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "mean", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(7); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/macrosProduct"].stateValues.value).eqls( - ["apply", "mean", ["*", 3, 17, 1]], - ); - expect( - stateVariables["/macrosProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/macrosProductSimplify"].stateValues.value, - ).eq(51); - expect( - stateVariables["/macrosProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "mean", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - 7, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus"].stateValues.value).eqls([ - "apply", - "mean", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlusSimplify"].stateValues.value, - ).eq(7); - expect( - stateVariables["/groupPlusSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus2"].stateValues.value).eqls([ - "apply", - "mean", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.value, - ).eq(7); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus3"].stateValues.value).eqls([ - "apply", - "mean", - ["tuple", 3, 17, 3, 17, 1, 1], - ]); - expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.value, - ).eq(7); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("mean additional cases", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Mean of first primes: 2 3 5 7

-

Copying that mean: $meanPrime{name="meanPrimeb"}

- $pPrime{name="pPrimeb"} - -

Mean of numbers from 1 to 100:

-

Copying that mean: $mean100{name="mean100b"}

- $p100{name="p100b"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.log("Test value displayed in browser"); - - cy.get(cesc("#\\/meanPrime")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4.25"); - }); - cy.get(cesc("#\\/meanPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4.25"); - }); - cy.get(cesc("#\\/pPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4.25"); - }); - cy.get(cesc("#\\/mean100")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("50.5"); - }); - cy.get(cesc("#\\/mean100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("50.5"); - }); - cy.get(cesc("#\\/p100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("50.5"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - expect(stateVariables["/meanPrime"].stateValues.value).eq(4.25); - expect(stateVariables["/meanPrimeb"].stateValues.value).eq( - 4.25, - ); - expect( - stateVariables[ - stateVariables["/pPrimeb"].activeChildren[1] - .componentName - ].stateValues.value, - ).eq(4.25); - expect(stateVariables["/mean100"].stateValues.value).eq(50.5); - expect(stateVariables["/mean100b"].stateValues.value).eq(50.5); - expect( - stateVariables[ - stateVariables["/p100b"].activeChildren[1].componentName - ].stateValues.value, - ).eq(50.5); - }); - }); - }); - - it("median", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 3175-4 - 1 4 5 10000 - 1 4 5 x+1 - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/numbers") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/sugared") + " .mjx-mrow") - .eq(0) - .should("have.text", "4.5"); - cy.get(cesc2("#/noSymbolic") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/numbers"].stateValues.value).eq(3); - expect(stateVariables["/numbers"].stateValues.isNumericOperator).eq( - true, - ); - expect(stateVariables["/numbers"].stateValues.isNumber).eq(true); - }); - }); - - // TODO: skipping most checks of ugly expressions for now - it("variance", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 6/2175-4 - 6/2175-4 - 6/2175-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - 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 theVariance = me.math.variance([3, 17, 1]); - let theVarianceString = theVariance.toString(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("32+172+12βˆ’(3+17+1)232"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("32+172+12βˆ’(3+17+1)232"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(62)2+172+12βˆ’(62+17+1)232"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/withNumberVariance")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - me.math - .variance([3, me.math.variance([17, 1])]) - .toString(), - ); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)232", - ); - }); - // cy.get(cesc('#\\/varsSimplify')).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('3x+2y+z3') - // }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)232", - ); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq( - theVariance, - ); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - // expect(stateVariables['/numbersForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(theVariance); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - // expect(stateVariables['/numbersWithNumberMathForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(theVariance); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/numbersWithNumericMath'].stateValues.value).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberVariance"].stateValues.value, - ).eq(me.math.variance([3, me.math.variance([17, 1])])); - expect( - stateVariables["/withNumberVariance"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberVariance"].stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/vars'].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - // expect(stateVariables['/varsSimplify'].stateValues.value).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq( - theVariance, - ); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - // expect(stateVariables["/varsb"].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("variance with sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 - 17 - 5-4 - 3 - 6/2 - 3175-4 - 3 17 1 - 3 17 1 - 3 17 1 - 6/2 17 5-4 - 6/2 17 5-4 - 6/2 17 5-4 - $a$b$c - $a$b$c - $a$b$c - $a $b $c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - xx+yx+y+z - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - `, - }, - "*", - ); - }); - - let theVariance = me.math.variance([3, 17, 1]); - let theVarianceString = theVariance.toString(); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("32+172+12βˆ’(3+17+1)232"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numericAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(62)2+172+(5βˆ’4)2βˆ’(62+17+5βˆ’4)232"); - }); - cy.get(cesc("#\\/numericAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numericAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersAsMacros")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("32+172+12βˆ’(3+17+1)232"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersAsMacros2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/withNumberMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("32+172+12βˆ’(3+17+1)232"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/withNumericMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(62)2+172+12βˆ’(62+17+1)232"); - }); - cy.get(cesc("#\\/withNumericMathMacroSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/withNumericMathMacroForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)232", - ); - }); - cy.get(cesc("#\\/varsAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)232", - ); - }); - // cy.get(cesc('#\\/varsAsStringSimplify')).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('3x+2y+z3') - // }); - cy.get(cesc("#\\/varsAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq( - theVariance, - ); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/numbersAsString"].stateValues.value).eq( - theVariance, - ); - expect( - stateVariables["/numbersAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsString"].stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/numbersAsStringForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/numericAsString'].stateValues.value).eqls(['/', ['+', ['/', 6, 2], 17, 5, -4], 3]); - expect( - stateVariables["/numericAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsString"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .value, - ).eq(theVariance); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .value, - ).eq(theVariance); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/numbersAsMacros"].stateValues.value).eq( - theVariance, - ); - expect( - stateVariables["/numbersAsMacros"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros"].stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/numbersAsMacrosForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersAsMacros2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/withNumberMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/withNumberMathMacroForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/withNumericMathMacro'].stateValues.value).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .value, - ).eq(theVariance); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/vars'].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - // expect(stateVariables['/varsAsString'].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/varsAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsAsString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - // expect(stateVariables['/varsAsStringSimplify'].stateValues.value).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .value, - ).eqls(NaN); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumber, - ).eq(false); - }); - }); - }); - - it("variance as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3 - 17 - 5-4 - - variance(3,17,5-4) - variance(3,17,5-4) - variance(3 17 5-4) - variance(3 17 5-4) - - variance(3,17,5-4) - - - variance(3,17,5-4) - - - variance(3175-4) - - - variance(3175-4) - - - variance($a,$b,$c) - - - variance($a,$b,$c) - - - variance($a$b$c) - - - variance($a$b$c) - - - variance($nums) - - - variance($nums) - - - variance($nums, $a, $b, 13) - - - variance($nums, $a, $b, 13) - - - variance($a, $b, 13, $nums) - - - variance($a, $b, 13, $nums) - - - variance($a, $b, $nums, 13) - - - variance($a, $b, $nums, 13) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let theVariance = me.math.variance([3, 17, 1]); - let theVarianceString = theVariance.toString(); - let theVariance2 = me.math.variance([3, 17, 1, 3, 17, 13]); - let theVariance2String = theVariance2.toString(); - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numberStringProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3β‹…17β‹…5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3,17,1)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numberComponentsProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/numberComponentsProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3,17,1)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/macrosProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/macrosProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3,17,1)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/groupPlus")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3,17,1,3,17,13)"); - }); - cy.get(cesc("#\\/groupPlusSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVariance2String); - }); - cy.get(cesc("#\\/groupPlus2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3,17,13,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlus2Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVariance2String); - }); - cy.get(cesc("#\\/groupPlus3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("variance(3,17,3,17,1,13)"); - }); - cy.get(cesc("#\\/groupPlus3Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVariance2String); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "variance", - ["tuple", 3, 17, ["+", 5, -4]], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numberStringProduct"].stateValues.value, - ).eqls(["apply", "variance", ["+", ["*", 3, 17, 5], -4]]); - expect( - stateVariables["/numberStringProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .value, - ).eq(0); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "variance", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsCommas"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .value, - ).eqls(["apply", "variance", ["*", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.value, - ).eq(0); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "variance", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/macrosProduct"].stateValues.value).eqls( - ["apply", "variance", ["*", 3, 17, 1]], - ); - expect( - stateVariables["/macrosProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/macrosProductSimplify"].stateValues.value, - ).eq(0); - expect( - stateVariables["/macrosProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "variance", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - theVariance, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus"].stateValues.value).eqls([ - "apply", - "variance", - ["tuple", 3, 17, 1, 3, 17, 13], - ]); - expect(stateVariables["/groupPlus"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlusSimplify"].stateValues.value, - ).eq(theVariance2); - expect( - stateVariables["/groupPlusSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus2"].stateValues.value).eqls([ - "apply", - "variance", - ["tuple", 3, 17, 13, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.value, - ).eq(theVariance2); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus3"].stateValues.value).eqls([ - "apply", - "variance", - ["tuple", 3, 17, 3, 17, 1, 13], - ]); - expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.value, - ).eq(theVariance2); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("variance additional cases", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Variance of first primes: 2 3 5 7

-

Copying that variance: $variancePrime{name="variancePrimeb"}

- $pPrime{name="pPrimeb"} - -

Variance of numbers from 1 to 100:

-

Copying that variance: $variance100{name="variance100b"}

- $p100{name="p100b"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let variancePrimes = me.math.variance(2, 3, 5, 7); - let variance100 = me.math.variance( - Array.from({ length: 100 }, (_, i) => i + 1), - ); - - cy.log("Test value displayed in browser"); - - cy.get(cesc("#\\/variancePrime")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variancePrimes, 1e-6); - }); - cy.get(cesc("#\\/variancePrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variancePrimes, 1e-6); - }); - cy.get(cesc("#\\/pPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variancePrimes, 1e-6); - }); - cy.get(cesc("#\\/variance100")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variance100, 1e-6); - }); - cy.get(cesc("#\\/variance100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variance100, 1e-6); - }); - cy.get(cesc("#\\/p100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variance100, 1e-6); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/variancePrime"].stateValues.value).closeTo( - variancePrimes, - 1e-12, - ); - expect(stateVariables["/variancePrimeb"].stateValues.value).closeTo( - variancePrimes, - 1e-12, - ); - expect( - stateVariables[ - stateVariables["/pPrimeb"].activeChildren[1].componentName - ].stateValues.value, - ).closeTo(variancePrimes, 1e-12); - expect(stateVariables["/variance100"].stateValues.value).closeTo( - variance100, - 1e-12, - ); - expect(stateVariables["/variance100b"].stateValues.value).closeTo( - variance100, - 1e-12, - ); - expect( - stateVariables[ - stateVariables["/p100b"].activeChildren[1].componentName - ].stateValues.value, - ).closeTo(variance100, 1e-12); - }); - }); - - // TODO: skipping most checks of ugly expressions for now - it("population variance", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 4165-4 - 4165-4 - 4165-4 - 4165-4 - 4165-4 - 4165-4 - 8/2165-4 - 8/2165-4 - 8/2165-4 - 4175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - 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 theVariance = me.math.variance([4, 16, 1], "uncorrected"); - let theVarianceString = theVariance.toString(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("42+162+12βˆ’(4+16+1)233"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("42+162+12βˆ’(4+16+1)233"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(82)2+162+12βˆ’(82+16+1)233"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/withNumberVariance")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - me.math - .variance( - [4, me.math.variance([17, 1], "uncorrected")], - "uncorrected", - ) - .toString(), - ); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)233", - ); - }); - // cy.get(cesc('#\\/varsSimplify')).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('3x+2y+z3') - // }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theVarianceString); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)233", - ); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq( - theVariance, - ); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - // expect(stateVariables['/numbersForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(theVariance); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - // expect(stateVariables['/numbersWithNumberMathForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(theVariance); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/numbersWithNumericMath'].stateValues.value).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(theVariance); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberVariance"].stateValues.value, - ).eq( - me.math.variance( - [4, me.math.variance([17, 1], "uncorrected")], - "uncorrected", - ), - ); - expect( - stateVariables["/withNumberVariance"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberVariance"].stateValues.isNumber, - ).eq(true); - // expect(stateVariables['/vars'].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - // expect(stateVariables['/varsSimplify'].stateValues.value).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq( - theVariance, - ); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - // expect(stateVariables["/varsb"].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("population variance additional cases", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Variance of first primes: 2 3 5 7

-

Copying that variance: $variancePrime{name="variancePrimeb"}

- $pPrime{name="pPrimeb"} - -

Variance of numbers from 1 to 100:

-

Copying that variance: $variance100{name="variance100b"}

- $p100{name="p100b"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let variancePrimes = me.math.variance([2, 3, 5, 7], "uncorrected"); - let variance100 = me.math.variance( - Array.from({ length: 100 }, (_, i) => i + 1), - "uncorrected", - ); - - cy.log("Test value displayed in browser"); - - cy.get(cesc("#\\/variancePrime")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variancePrimes, 1e-6); - }); - cy.get(cesc("#\\/variancePrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variancePrimes, 1e-6); - }); - cy.get(cesc("#\\/pPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variancePrimes, 1e-6); - }); - cy.get(cesc("#\\/variance100")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variance100, 1e-6); - }); - cy.get(cesc("#\\/variance100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variance100, 1e-6); - }); - cy.get(cesc("#\\/p100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(variance100, 1e-6); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/variancePrime"].stateValues.value).closeTo( - variancePrimes, - 1e-12, - ); - expect(stateVariables["/variancePrimeb"].stateValues.value).closeTo( - variancePrimes, - 1e-12, - ); - expect( - stateVariables[ - stateVariables["/pPrimeb"].activeChildren[1].componentName - ].stateValues.value, - ).closeTo(variancePrimes, 1e-12); - expect(stateVariables["/variance100"].stateValues.value).closeTo( - variance100, - 1e-12, - ); - expect(stateVariables["/variance100b"].stateValues.value).closeTo( - variance100, - 1e-12, - ); - expect( - stateVariables[ - stateVariables["/p100b"].activeChildren[1].componentName - ].stateValues.value, - ).closeTo(variance100, 1e-12); - }); - }); - - // TODO: skipping most checks of ugly expressions for now - it("standard deviation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 6/2175-4 - 6/2175-4 - 6/2175-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - 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 theStandardDeviation = me.math.std([3, 17, 1]); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(theStandardDeviation, 1e-6); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√32+172+12βˆ’(3+17+1)232"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√76"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(theStandardDeviation, 1e-6); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√32+172+12βˆ’(3+17+1)232"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√76"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√(62)2+172+12βˆ’(62+17+1)232"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√76"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(theStandardDeviation, 1e-6); - }); - cy.get(cesc("#\\/withNumberStandardDeviation")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo( - me.math.std([3, me.math.std([17, 1])]), - 1e-6, - ); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "√x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)232", - ); - }); - // cy.get(cesc('#\\/varsSimplify')).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('3x+2y+z3') - // }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(theStandardDeviation, 1e-6); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "√x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)232", - ); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).closeTo( - theStandardDeviation, - 1e-12, - ); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - // expect(stateVariables['/numbersForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eqls(["apply", "sqrt", 76]); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).closeTo(theStandardDeviation, 1e-16); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - // expect(stateVariables['/numbersWithNumberMathForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eqls(["apply", "sqrt", 76]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(false); - // expect(stateVariables['/numbersWithNumericMath'].stateValues.value).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eqls(["apply", "sqrt", 76]); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).closeTo(theStandardDeviation, 1e-12); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberStandardDeviation"].stateValues - .value, - ).closeTo(me.math.std([3, me.math.std([17, 1])]), 1e-12); - expect( - stateVariables["/withNumberStandardDeviation"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberStandardDeviation"].stateValues - .isNumber, - ).eq(true); - // expect(stateVariables['/vars'].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - // expect(stateVariables['/varsSimplify'].stateValues.value).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).closeTo( - theStandardDeviation, - 1e-12, - ); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - // expect(stateVariables["/varsb"].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("standard deviation as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 13 - 25 - 5-4 - - std(13,25,5-4) - std(13,25,5-4) - std(13 25 5-4) - std(13 25 5-4) - - std(13,25,5-4) - - - std(13,25,5-4) - - - std(13255-4) - - - std(13255-4) - - - std($a,$b,$c) - - - std($a,$b,$c) - - - std($a$b$c) - - - std($a$b$c) - - - std($nums) - - - std($nums) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let theStd = me.math.std([13, 25, 1]); - let theStdString = theStd.toString(); - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("std(13,25,5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theStdString); - }); - cy.get(cesc("#\\/numberStringProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("std(13β‹…25β‹…5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("std(13,25,1)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theStdString); - }); - cy.get(cesc("#\\/numberComponentsProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("std(13β‹…25β‹…1)"); - }); - cy.get(cesc("#\\/numberComponentsProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("std(13,25,1)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theStdString); - }); - cy.get(cesc("#\\/macrosProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("std(13β‹…25β‹…1)"); - }); - cy.get(cesc("#\\/macrosProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("std(13,25,1)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(theStdString); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "std", - ["tuple", 13, 25, ["+", 5, -4]], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(theStd); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numberStringProduct"].stateValues.value, - ).eqls(["apply", "std", ["+", ["*", 13, 25, 5], -4]]); - expect( - stateVariables["/numberStringProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .value, - ).eq(0); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "std", ["tuple", 13, 25, 1]]); - expect( - stateVariables["/numberComponentsCommas"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(theStd); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .value, - ).eqls(["apply", "std", ["*", 13, 25, 1]]); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.value, - ).eq(0); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "std", - ["tuple", 13, 25, 1], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(theStd); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/macrosProduct"].stateValues.value).eqls( - ["apply", "std", ["*", 13, 25, 1]], - ); - expect( - stateVariables["/macrosProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/macrosProductSimplify"].stateValues.value, - ).eq(0); - expect( - stateVariables["/macrosProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "std", - ["tuple", 13, 25, 1], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - theStd, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("standard deviation additional cases", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Standard deviation of first primes: 2 3 5 7

-

Copying that standard deviation: $standarddeviationPrime{name="standarddeviationPrimeb"}

- $pPrime{name="pPrimeb"} - -

Standard deviation of numbers from 1 to 100:

-

Copying that standard deviation: $standarddeviation100{name="standarddeviation100b"}

- $p100{name="p100b"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let stdPrimes = me.math.std(2, 3, 5, 7); - let std100 = me.math.std(Array.from({ length: 100 }, (_, i) => i + 1)); - - cy.log("Test value displayed in browser"); - - cy.get(cesc("#\\/standarddeviationPrime")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(stdPrimes, 1e-6); - }); - cy.get(cesc("#\\/standarddeviationPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(stdPrimes, 1e-6); - }); - cy.get(cesc("#\\/pPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(stdPrimes, 1e-6); - }); - cy.get(cesc("#\\/standarddeviation100")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(std100, 1e-6); - }); - cy.get(cesc("#\\/standarddeviation100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(std100, 1e-6); - }); - cy.get(cesc("#\\/p100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(std100, 1e-6); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/standarddeviationPrime"].stateValues.value, - ).closeTo(stdPrimes, 1e-12); - expect( - stateVariables["/standarddeviationPrimeb"].stateValues.value, - ).closeTo(stdPrimes, 1e-12); - expect( - stateVariables[ - stateVariables["/pPrimeb"].activeChildren[1].componentName - ].stateValues.value, - ).closeTo(stdPrimes, 1e-12); - expect( - stateVariables["/standarddeviation100"].stateValues.value, - ).closeTo(std100, 1e-12); - expect( - stateVariables["/standarddeviation100b"].stateValues.value, - ).closeTo(std100, 1e-12); - expect( - stateVariables[ - stateVariables["/p100b"].activeChildren[1].componentName - ].stateValues.value, - ).closeTo(std100, 1e-12); - }); - }); - - // TODO: skipping most checks of ugly expressions for now - it("population standard deviation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 4165-4 - 4165-4 - 4165-4 - 4165-4 - 4165-4 - 4165-4 - 8/2165-4 - 8/2165-4 - 8/2165-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - 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 theStandardDeviation = me.math.std([4, 16, 1], "uncorrected"); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(theStandardDeviation, 1e-6); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√42+162+12βˆ’(4+16+1)233"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√42"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(theStandardDeviation, 1e-6); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√42+162+12βˆ’(4+16+1)233"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√42"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√(82)2+162+12βˆ’(82+16+1)233"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√42"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(theStandardDeviation, 1e-6); - }); - cy.get(cesc("#\\/withNumberStandardDeviation")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo( - me.math.std( - [3, me.math.std([17, 1], "uncorrected")], - "uncorrected", - ), - 1e-6, - ); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "√x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)233", - ); - }); - // cy.get(cesc('#\\/varsSimplify')).find('.mjx-mrow').eq(0).invoke('text').then((text) => { - // expect(text.trim()).equal('3x+2y+z3') - // }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(theStandardDeviation, 1e-6); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "√x2+(x+y)2+(x+y+z)2βˆ’(x+x+y+x+y+z)233", - ); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).closeTo( - theStandardDeviation, - 1e-12, - ); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - // expect(stateVariables['/numbersForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eqls(["apply", "sqrt", 42]); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).closeTo(theStandardDeviation, 1e-16); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - // expect(stateVariables['/numbersWithNumberMathForceSymbolic'].stateValues.value).eqls(['/', ['+', 3, 17, 1], 3]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eqls(["apply", "sqrt", 42]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(false); - // expect(stateVariables['/numbersWithNumericMath'].stateValues.value).eqls(['/', ['+', ['/', 6, 2], 17, 1], 3]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eqls(["apply", "sqrt", 42]); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).closeTo(theStandardDeviation, 1e-12); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberStandardDeviation"].stateValues - .value, - ).closeTo( - me.math.std( - [3, me.math.std([17, 1], "uncorrected")], - "uncorrected", - ), - 1e-12, - ); - expect( - stateVariables["/withNumberStandardDeviation"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberStandardDeviation"].stateValues - .isNumber, - ).eq(true); - // expect(stateVariables['/vars'].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - // expect(stateVariables['/varsSimplify'].stateValues.value).eqls(['/', ['+', ['*', 3, 'x'], ['*', 2, 'y'], 'z'], 3]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).closeTo( - theStandardDeviation, - 1e-12, - ); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - // expect(stateVariables["/varsb"].stateValues.value).eqls(['/', ['+', 'x', 'x', 'y', 'x', 'y', 'z'], 3]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("population standard deviation additional cases", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Standard deviation of first primes: 2 3 5 7

-

Copying that standard deviation: $standarddeviationPrime{name="standarddeviationPrimeb"}

- $pPrime{name="pPrimeb"} - -

Standard deviation of numbers from 1 to 100:

-

Copying that standard deviation: $standarddeviation100{name="standarddeviation100b"}

- $p100{name="p100b"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let stdPrimes = me.math.std([2, 3, 5, 7], "uncorrected"); - let std100 = me.math.std( - Array.from({ length: 100 }, (_, i) => i + 1), - "uncorrected", - ); - - cy.log("Test value displayed in browser"); - - cy.get(cesc("#\\/standarddeviationPrime")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(stdPrimes, 1e-6); - }); - cy.get(cesc("#\\/standarddeviationPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(stdPrimes, 1e-6); - }); - cy.get(cesc("#\\/pPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(stdPrimes, 1e-6); - }); - cy.get(cesc("#\\/standarddeviation100")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(std100, 1e-6); - }); - cy.get(cesc("#\\/standarddeviation100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(std100, 1e-6); - }); - cy.get(cesc("#\\/p100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(std100, 1e-6); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/standarddeviationPrime"].stateValues.value, - ).closeTo(stdPrimes, 1e-12); - expect( - stateVariables["/standarddeviationPrimeb"].stateValues.value, - ).closeTo(stdPrimes, 1e-12); - expect( - stateVariables[ - stateVariables["/pPrimeb"].activeChildren[1].componentName - ].stateValues.value, - ).closeTo(stdPrimes, 1e-12); - expect( - stateVariables["/standarddeviation100"].stateValues.value, - ).closeTo(std100, 1e-12); - expect( - stateVariables["/standarddeviation100b"].stateValues.value, - ).closeTo(std100, 1e-12); - expect( - stateVariables[ - stateVariables["/p100b"].activeChildren[1].componentName - ].stateValues.value, - ).closeTo(std100, 1e-12); - }); - }); - - it("count", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 6/2175-4 - 6/2175-4 - 6/2175-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/withNumberCount")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/varsSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(3); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(3); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(3); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/withNumberCount"].stateValues.value).eq( - 2, - ); - expect( - stateVariables["/withNumberCount"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberCount"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eq(3); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/vars"].stateValues.isNumber).eq(true); - expect(stateVariables["/varsSimplify"].stateValues.value).eq(3); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(true); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eq(3); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.value).eq(3); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/varsb"].stateValues.value).eq(3); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(true); - }); - }); - }); - - it("count with sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 - 17 - 5-4 - 3 - 6/2 - 3175-4 - 3 17 1 - 3 17 1 - 3 17 1 - 6/2 17 5-4 - 6/2 17 5-4 - 6/2 17 5-4 - $a$b$c - $a$b$c - $a$b$c - $a $b $c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - xx+yx+y+z - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numericAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numericAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numericAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersAsMacros")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersAsMacros2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/withNumberMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/withNumericMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/withNumericMathMacroSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/withNumericMathMacroForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/varsAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/varsAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/varsAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(3); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/numbersAsString"].stateValues.value).eq( - 3, - ); - expect( - stateVariables["/numbersAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsString"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .value, - ).eq(3); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/numericAsString"].stateValues.value).eq( - 3, - ); - expect( - stateVariables["/numericAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsString"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .value, - ).eq(3); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .value, - ).eq(3); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/numbersAsMacros"].stateValues.value).eq( - 3, - ); - expect( - stateVariables["/numbersAsMacros"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .value, - ).eq(3); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.value, - ).eq(3); - expect( - stateVariables["/numbersAsMacros2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.value, - ).eq(3); - expect( - stateVariables["/withNumberMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacro"].stateValues.value, - ).eq(3); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .value, - ).eq(3); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eq(3); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/vars"].stateValues.isNumber).eq(true); - expect(stateVariables["/varsAsString"].stateValues.value).eq(3); - expect( - stateVariables["/varsAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect(stateVariables["/varsAsString"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/varsAsStringSimplify"].stateValues.value, - ).eq(3); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .value, - ).eq(3); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - }); - }); - }); - - // need to upgrade mathjs to get the count function - it.skip("count as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3 - 17 - 5-4 - - count(3,17,5-4) - count(3,17,5-4) - count(3 17 5-4) - count(3 17 5-4) - - count(3,17,5-4) - - - count(3,17,5-4) - - - count(3175-4) - - - count(3175-4) - - - count($a,$b,$c) - - - count($a,$b,$c) - - - count($a$b$c) - - - count($a$b$c) - - - count($nums) - - - count($nums) - - - count($nums, $a, $b, $c) - - - count($nums, $a, $b, $c) - - - count($a, $b, $c, $nums) - - - count($a, $b, $c, $nums) - - - count($a, $b, $nums, $c) - - - count($a, $b, $nums, $c) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numberStringProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3β‹…17β‹…5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3,17,1)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numberComponentsProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/numberComponentsProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3,17,1)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/macrosProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/macrosProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3,17,1)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/groupPlus")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlusSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(cesc("#\\/groupPlus2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlus2Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(cesc("#\\/groupPlus3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("count(3,17,3,17,1,1)"); - }); - cy.get(cesc("#\\/groupPlus3Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "count", - ["tuple", 3, 17, ["+", 5, -4]], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(3); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numberStringProduct"].stateValues.value, - ).eqls(["apply", "count", ["+", ["*", 3, 17, 5], -4]]); - expect( - stateVariables["/numberStringProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .value, - ).eq(1); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "count", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsCommas"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(3); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .value, - ).eqls(["apply", "count", ["*", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.value, - ).eq(1); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "count", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(3); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/macrosProduct"].stateValues.value).eqls( - ["apply", "count", ["*", 3, 17, 1]], - ); - expect( - stateVariables["/macrosProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/macrosProductSimplify"].stateValues.value, - ).eq(1); - expect( - stateVariables["/macrosProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "count", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - 3, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus"].stateValues.value).eqls([ - "apply", - "count", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlusSimplify"].stateValues.value, - ).eq(6); - expect( - stateVariables["/groupPlusSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus2"].stateValues.value).eqls([ - "apply", - "count", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.value, - ).eq(6); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus3"].stateValues.value).eqls([ - "apply", - "count", - ["tuple", 3, 17, 3, 17, 1, 1], - ]); - expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.value, - ).eq(6); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("count additional cases", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Count of first primes: 2 3 5 7

-

Copying that count: $countPrime{name="countPrimeb"}

- $pPrime{name="pPrimeb"} - -

Count of numbers from 1 to 100:

-

Copying that count: $count100{name="count100b"}

- $p100{name="p100b"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.log("Test value displayed in browser"); - - cy.get(cesc("#\\/countPrime")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/countPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/pPrimeb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/count100")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("100"); - }); - cy.get(cesc("#\\/count100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("100"); - }); - cy.get(cesc("#\\/p100b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("100"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - expect(stateVariables["/countPrime"].stateValues.value).eq(4); - expect(stateVariables["/countPrimeb"].stateValues.value).eq(4); - expect( - stateVariables[ - stateVariables["/pPrimeb"].activeChildren[1] - .componentName - ].stateValues.value, - ).eq(4); - expect(stateVariables["/count100"].stateValues.value).eq(100); - expect(stateVariables["/count100b"].stateValues.value).eq(100); - expect( - stateVariables[ - stateVariables["/p100b"].activeChildren[1].componentName - ].stateValues.value, - ).eq(100); - }); - }); - }); - - it("min", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 6/2175-4 - 6/2175-4 - 6/2175-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1)"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1)"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(62,17,1)"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/withNumberMin")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(x,x+y,x+y+z)"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(1); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(1); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(1); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(1); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eqls(["apply", "min", ["tuple", ["/", 6, 2], 17, 1]]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(1); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(1); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/withNumberMin"].stateValues.value).eq( - 1, - ); - expect( - stateVariables["/withNumberMin"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMin"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq(1); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/varsb"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("min with sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 - 17 - 5-4 - 3 - 6/2 - 3175-4 - 3 17 1 - 3 17 1 - 3 17 1 - 6/2 17 5-4 - 6/2 17 5-4 - 6/2 17 5-4 - $a$b$c - $a$b$c - $a$b$c - $a $b $c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - xx+yx+y+z - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1)"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numericAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(62,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numericAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numericAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersAsMacros")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1)"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numbersAsMacros2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/withNumberMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1)"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/withNumericMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(62,17,1)"); - }); - cy.get(cesc("#\\/withNumericMathMacroSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/withNumericMathMacroForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(1); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/numbersAsString"].stateValues.value).eq( - 1, - ); - expect( - stateVariables["/numbersAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsString"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .value, - ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.value, - ).eq(1); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numericAsString"].stateValues.value, - ).eqls([ - "apply", - "min", - ["tuple", ["/", 6, 2], 17, ["+", 5, -4]], - ]); - expect( - stateVariables["/numericAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsString"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .value, - ).eq(1); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .value, - ).eq(1); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/numbersAsMacros"].stateValues.value).eq( - 1, - ); - expect( - stateVariables["/numbersAsMacros"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .value, - ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.value, - ).eq(1); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.value, - ).eq(1); - expect( - stateVariables["/numbersAsMacros2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.value, - ).eq(1); - expect( - stateVariables["/withNumberMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.value, - ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.value, - ).eq(1); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacro"].stateValues.value, - ).eqls(["apply", "min", ["tuple", ["/", 6, 2], 17, 1]]); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .value, - ).eq(1); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.value, - ).eq(1); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsAsString"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/varsAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsAsString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsAsStringSimplify"].stateValues.value, - ).eqls([ - "apply", - "min", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .value, - ).eqls(NaN); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumber, - ).eq(false); - }); - }); - }); - - it("min as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3 - 17 - 5-4 - - min(3,17,5-4) - min(3,17,5-4) - min(3 17 5-4) - min(3 17 5-4) - - min(3,17,5-4) - - - min(3,17,5-4) - - - min(3175-4) - - - min(3175-4) - - - min($a,$b,$c) - - - min($a,$b,$c) - - - min($a$b$c) - - - min($a$b$c) - - - min($nums) - - - min($nums) - - - min($nums, $a, $b, $c) - - - min($nums, $a, $b, $c) - - - min($a, $b, $c, $nums) - - - min($a, $b, $c, $nums) - - - min($a, $b, $nums, $c) - - - min($a, $b, $nums, $c) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numberStringProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3β‹…17β‹…5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("251"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/numberComponentsProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/numberComponentsProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/macrosProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/macrosProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/groupPlus")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlusSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/groupPlus2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlus2Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/groupPlus3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("min(3,17,3,17,1,1)"); - }); - cy.get(cesc("#\\/groupPlus3Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", 3, 17, ["+", 5, -4]], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(1); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numberStringProduct"].stateValues.value, - ).eqls(["apply", "min", ["+", ["*", 3, 17, 5], -4]]); - expect( - stateVariables["/numberStringProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .value, - ).eq(251); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "min", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsCommas"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(1); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .value, - ).eqls(["apply", "min", ["*", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(1); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/macrosProduct"].stateValues.value).eqls( - ["apply", "min", ["*", 3, 17, 1]], - ); - expect( - stateVariables["/macrosProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/macrosProductSimplify"].stateValues.value, - ).eq(51); - expect( - stateVariables["/macrosProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - 1, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlusSimplify"].stateValues.value, - ).eq(1); - expect( - stateVariables["/groupPlusSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus2"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.value, - ).eq(1); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus3"].stateValues.value).eqls([ - "apply", - "min", - ["tuple", 3, 17, 3, 17, 1, 1], - ]); - expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.value, - ).eq(1); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("min can be invertible", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 36 - 36 - 36 - 36 - - 36 - 36 - 36 - 36 - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should("contain.text", "1"); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should("contain.text", "3"); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}8{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{backspace}8{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths01") + " .mjx-mrow").should("contain.text", "6"); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should( - "contain.text", - "min(3,x)", - ); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "min(x,6)"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "min(3,x)"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{shift+home}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{shift+home}{backspace}y{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should( - "contain.text", - "min(3,y)", - ); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "min(y,6)"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "min(3,y)"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{shift+home}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{shift+home}{backspace}2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should("contain.text", "2"); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - }); - - it("max", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 3175-4 - 6/2175-4 - 6/2175-4 - 6/2175-4 - 3175-4 - xx+yx+y+z - xx+yx+y+z - xx+yx+y+z - $numbers{name="numbersb"} - $vars{name="varsb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1)"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1)"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(62,17,1)"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/withNumberMax")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsForcedNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/varsb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(x,x+y,x+y+z)"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(17); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(17); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(17); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(17); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eqls(["apply", "max", ["tuple", ["/", 6, 2], 17, 1]]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(17); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(17); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/withNumberMax"].stateValues.value).eq( - 17, - ); - expect( - stateVariables["/withNumberMax"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMax"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/varsSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsSimplify"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsForcedNumeric"].stateValues.value, - ).eqls(NaN); - expect( - stateVariables["/varsForcedNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsForcedNumeric"].stateValues.isNumber, - ).eq(false); - expect(stateVariables["/numbersb"].stateValues.value).eq(17); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/varsb"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/varsb"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/varsb"].stateValues.isNumber).eq(false); - }); - }); - }); - - it("max with sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3 - 17 - 5-4 - 3 - 6/2 - 3175-4 - 3 17 1 - 3 17 1 - 3 17 1 - 6/2 17 5-4 - 6/2 17 5-4 - 6/2 17 5-4 - $a$b$c - $a$b$c - $a$b$c - $a $b $c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumberMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - $aNumericMath$b$c - xx+yx+y+z - x x+y x+y+z - x x+y x+y+z - x x+y x+y+z - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1)"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numericAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(62,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numericAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numericAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersAsMacros")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1)"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numbersAsMacros2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/withNumberMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1)"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/withNumericMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(62,17,1)"); - }); - cy.get(cesc("#\\/withNumericMathMacroSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/withNumericMathMacroForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/vars")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(x,x+y,x+y+z)"); - }); - cy.get(cesc("#\\/varsAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(17); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/numbersAsString"].stateValues.value).eq( - 17, - ); - expect( - stateVariables["/numbersAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsString"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .value, - ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.value, - ).eq(17); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numericAsString"].stateValues.value, - ).eqls([ - "apply", - "max", - ["tuple", ["/", 6, 2], 17, ["+", 5, -4]], - ]); - expect( - stateVariables["/numericAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsString"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .value, - ).eq(17); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .value, - ).eq(17); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/numbersAsMacros"].stateValues.value).eq( - 17, - ); - expect( - stateVariables["/numbersAsMacros"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .value, - ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.value, - ).eq(17); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.value, - ).eq(17); - expect( - stateVariables["/numbersAsMacros2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.value, - ).eq(17); - expect( - stateVariables["/withNumberMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.value, - ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.value, - ).eq(17); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacro"].stateValues.value, - ).eqls(["apply", "max", ["tuple", ["/", 6, 2], 17, 1]]); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .value, - ).eq(17); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.value, - ).eq(17); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/vars"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/vars"].stateValues.isNumericOperator, - ).eq(false); - expect(stateVariables["/vars"].stateValues.isNumber).eq(false); - expect(stateVariables["/varsAsString"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/varsAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect(stateVariables["/varsAsString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/varsAsStringSimplify"].stateValues.value, - ).eqls([ - "apply", - "max", - ["tuple", "x", ["+", "x", "y"], ["+", "x", "y", "z"]], - ]); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/varsAsStringSimplify"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .value, - ).eqls(NaN); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/varsAsStringForceNumeric"].stateValues - .isNumber, - ).eq(false); - }); - }); - }); - - it("max as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3 - 17 - 5-4 - - max(3,17,5-4) - max(3,17,5-4) - max(3 17 5-4) - max(3 17 5-4) - - max(3,17,5-4) - - - max(3,17,5-4) - - - max(3175-4) - - - max(3175-4) - - - max($a,$b,$c) - - - max($a,$b,$c) - - - max($a$b$c) - - - max($a$b$c) - - - max($nums) - - - max($nums) - - - max($nums, $a, $b, $c) - - - max($nums, $a, $b, $c) - - - max($a, $b, $c, $nums) - - - max($a, $b, $c, $nums) - - - max($a, $b, $nums, $c) - - - max($a, $b, $nums, $c) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numberStringProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3β‹…17β‹…5βˆ’4)"); - }); - cy.get(cesc("#\\/numberStringProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("251"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/numberComponentsProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/numberComponentsProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/macrosProduct")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3β‹…17β‹…1)"); - }); - cy.get(cesc("#\\/macrosProductSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("51"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/groupPlus")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlusSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/groupPlus2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,1,3,17,1)"); - }); - cy.get(cesc("#\\/groupPlus2Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - cy.get(cesc("#\\/groupPlus3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("max(3,17,3,17,1,1)"); - }); - cy.get(cesc("#\\/groupPlus3Simplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("17"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", 3, 17, ["+", 5, -4]], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(17); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numberStringProduct"].stateValues.value, - ).eqls(["apply", "max", ["+", ["*", 3, 17, 5], -4]]); - expect( - stateVariables["/numberStringProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .value, - ).eq(251); - expect( - stateVariables["/numberStringProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "max", ["tuple", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsCommas"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(17); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .value, - ).eqls(["apply", "max", ["*", 3, 17, 1]]); - expect( - stateVariables["/numberComponentsProduct"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.value, - ).eq(51); - expect( - stateVariables["/numberComponentsProductSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(17); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/macrosProduct"].stateValues.value).eqls( - ["apply", "max", ["*", 3, 17, 1]], - ); - expect( - stateVariables["/macrosProduct"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/macrosProductSimplify"].stateValues.value, - ).eq(51); - expect( - stateVariables["/macrosProductSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", 3, 17, 1], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - 17, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlusSimplify"].stateValues.value, - ).eq(17); - expect( - stateVariables["/groupPlusSimplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus2"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", 3, 17, 1, 3, 17, 1], - ]); - expect(stateVariables["/groupPlus2"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.value, - ).eq(17); - expect( - stateVariables["/groupPlus2Simplify"].stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/groupPlus3"].stateValues.value).eqls([ - "apply", - "max", - ["tuple", 3, 17, 3, 17, 1, 1], - ]); - expect(stateVariables["/groupPlus3"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.value, - ).eq(17); - expect( - stateVariables["/groupPlus3Simplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("max can be invertible", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 36 - 36 - 36 - 36 - - 36 - 36 - 36 - 36 - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}9{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{backspace}9{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should("contain.text", "9"); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should("contain.text", "5"); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should("contain.text", "3"); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should( - "contain.text", - "max(3,x)", - ); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "max(x,6)"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "max(3,x)"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{shift+home}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{shift+home}{backspace}y{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should( - "contain.text", - "max(3,y)", - ); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "NaN"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "max(y,6)"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "max(3,y)"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/minumbers00") + " textarea").type( - "{end}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers11") + " textarea").type( - "{end}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers01") + " textarea").type( - "{end}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/minumbers10") + " textarea").type( - "{end}{backspace}7{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mimaths00") + " textarea").type( - "{end}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths11") + " textarea").type( - "{end}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths01") + " textarea").type( - "{end}{shift+home}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mimaths10") + " textarea").type( - "{end}{shift+home}{backspace}7{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/maths10") + " .mjx-mrow").should("contain.text", "7"); - - cy.get(cesc("#\\/numbers00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/numbers01") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc("#\\/numbers10") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc("#\\/numbers11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - - cy.get(cesc("#\\/maths00") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc("#\\/maths01") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc("#\\/maths10") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc("#\\/maths11") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - }); - - it("mod", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 173 - 173 - 173 - 173 - 173 - 173 - 176/2 - 176/2 - 176/2 - 17169 - $numbers{name="numbersb"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/numbersForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersWithNumberMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/numbersWithNumberMathForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersWithNumericMath")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,62)"); - }); - cy.get(cesc("#\\/numbersWithNumericMathSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersWithNumericMathForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/withNumberMod")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/numbersb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(2); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect( - stateVariables["/numbersForceSymbolic"].stateValues.value, - ).eqls(["apply", "mod", ["tuple", 17, 3]]); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .value, - ).eq(2); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersForceSymbolicSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues.value, - ).eq(2); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMath"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.value, - ).eqls(["apply", "mod", ["tuple", 17, 3]]); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumberMathForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.value, - ).eq(2); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables[ - "/numbersWithNumberMathForceSymbolicSimplify" - ].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMath"].stateValues.value, - ).eqls(["apply", "mod", ["tuple", 17, ["/", 6, 2]]]); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMath"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.value, - ).eq(2); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersWithNumericMathSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.value, - ).eq(2); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersWithNumericMathForceNumeric"] - .stateValues.isNumber, - ).eq(true); - expect(stateVariables["/withNumberMod"].stateValues.value).eq( - 3, - ); - expect( - stateVariables["/withNumberMod"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMod"].stateValues.isNumber, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.value).eq(2); - expect( - stateVariables["/numbersb"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbersb"].stateValues.isNumber).eq( - true, - ); - }); - }); - }); - - it("mod with sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 17 - 3 - 3 - 6/2 - 173 - 17 3 - 17 3 - 17 3 - 17 6/2 - 17 6/2 - 17 6/2 - $a$b - $a$b - $a$b - $a $b - $a$bNumberMath - $a$bNumberMath - $a$bNumberMath - $a$bNumericMath - $a$bNumericMath - $a$bNumericMath - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numbers")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/numbersAsStringForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numericAsString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,62)"); - }); - cy.get(cesc("#\\/numericAsStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numericAsStringForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersAsMacros")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/numbersAsMacrosForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numbersAsMacros2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/withNumberMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/withNumberMathMacroForceSymbolicSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/withNumericMathMacro")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,62)"); - }); - cy.get(cesc("#\\/withNumericMathMacroSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/withNumericMathMacroForceNumeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numbers"].stateValues.value).eq(2); - expect( - stateVariables["/numbers"].stateValues.isNumericOperator, - ).eq(true); - expect(stateVariables["/numbers"].stateValues.isNumber).eq( - true, - ); - expect(stateVariables["/numbersAsString"].stateValues.value).eq( - 2, - ); - expect( - stateVariables["/numbersAsString"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsString"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .value, - ).eqls(["apply", "mod", ["tuple", 17, 3]]); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.value, - ).eq(2); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsStringForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numericAsString"].stateValues.value, - ).eqls(["apply", "mod", ["tuple", 17, ["/", 6, 2]]]); - expect( - stateVariables["/numericAsString"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsString"].stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .value, - ).eq(2); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numericAsStringSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .value, - ).eq(2); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numericAsStringForceNumeric"].stateValues - .isNumber, - ).eq(true); - expect(stateVariables["/numbersAsMacros"].stateValues.value).eq( - 2, - ); - expect( - stateVariables["/numbersAsMacros"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .value, - ).eqls(["apply", "mod", ["tuple", 17, 3]]); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolic"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.value, - ).eq(2); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/numbersAsMacrosForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.value, - ).eq(2); - expect( - stateVariables["/numbersAsMacros2"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/numbersAsMacros2"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.value, - ).eq(2); - expect( - stateVariables["/withNumberMathMacro"].stateValues - .isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumberMathMacro"].stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.value, - ).eqls(["apply", "mod", ["tuple", 17, 3]]); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolic"] - .stateValues.isNumber, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.value, - ).eq(2); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumberMathMacroForceSymbolicSimplify"] - .stateValues.isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacro"].stateValues.value, - ).eqls(["apply", "mod", ["tuple", 17, ["/", 6, 2]]]); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacro"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .value, - ).eq(2); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumericOperator, - ).eq(false); - expect( - stateVariables["/withNumericMathMacroSimplify"].stateValues - .isNumber, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.value, - ).eq(2); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumericOperator, - ).eq(true); - expect( - stateVariables["/withNumericMathMacroForceNumeric"] - .stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("mod as math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 17 - 3 - - mod(17,3) - mod(17,3) - - mod(17,3) - - - mod(17,3) - - - mod($a,$b) - - - mod($a,$b) - - - mod($nums) - - - mod($nums) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/numberString")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/numberStringSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/numberComponentsCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/numberComponentsCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/macrosCommas")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/macrosCommasSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/group")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("mod(17,3)"); - }); - cy.get(cesc("#\\/groupSimplify")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - cy.window().then(async (win) => { - expect(stateVariables["/numberString"].stateValues.value).eqls([ - "apply", - "mod", - ["tuple", 17, 3], - ]); - expect(stateVariables["/numberString"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/numberStringSimplify"].stateValues.value, - ).eq(2); - expect( - stateVariables["/numberStringSimplify"].stateValues - .isNumber, - ).eq(true); - - expect( - stateVariables["/numberComponentsCommas"].stateValues.value, - ).eqls(["apply", "mod", ["tuple", 17, 3]]); - expect( - stateVariables["/numberComponentsCommas"].stateValues - .isNumber, - ).eq(false); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.value, - ).eq(2); - expect( - stateVariables["/numberComponentsCommasSimplify"] - .stateValues.isNumber, - ).eq(true); - - expect(stateVariables["/macrosCommas"].stateValues.value).eqls([ - "apply", - "mod", - ["tuple", 17, 3], - ]); - expect(stateVariables["/macrosCommas"].stateValues.isNumber).eq( - false, - ); - expect( - stateVariables["/macrosCommasSimplify"].stateValues.value, - ).eq(2); - expect( - stateVariables["/macrosCommasSimplify"].stateValues - .isNumber, - ).eq(true); - - expect(stateVariables["/group"].stateValues.value).eqls([ - "apply", - "mod", - ["tuple", 17, 3], - ]); - expect(stateVariables["/group"].stateValues.isNumber).eq(false); - expect(stateVariables["/groupSimplify"].stateValues.value).eq( - 2, - ); - expect( - stateVariables["/groupSimplify"].stateValues.isNumber, - ).eq(true); - }); - }); - }); - - it("gcd", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 13581 - 135 81 63 - x y z - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/_gcd1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("27"); - }); - cy.get(cesc("#\\/_gcd2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc("#\\/_gcd3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("gcd(x,y,z)"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/_gcd1"].stateValues.value).eq(27); - expect(stateVariables["/_gcd2"].stateValues.value).eq(9); - expect(stateVariables["/_gcd3"].stateValues.value).eqls([ - "apply", - "gcd", - ["tuple", "x", "y", "z"], - ]); - }); - }); - - it("extract parts of math expression", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

original expression: f(x)+g(y,z)+h(q)

-

Operator: $expr

-

Number of operands: $expr

-

First operand: $expr

-

Second operand: $expr

-

Third operand: $expr

-

No fourth operand: $expr

-

Function from first operand: $operand1

-

Function from second operand: $operand2

-

No function from third operand: $operand3

-

Function argument from first operand: $operand1

-

Function argument from first operand again: $operand1

-

No second function argument from first operand: $operand1

-

All function arguments from second operand: $operand2

-

First function argument from second operand: $operand2

-

Second function argument from second operand: $operand2

-

No third function argument from second operand: $operand2

-

No function argument from third operand: $operand3

-

Number of operands from first operand: $operand1

-

First operand from first operand: $operand1

- - -

Pick operand number:

-

Resulting operand: $expr

-

Function of resulting operand: $operandN

-

Pick argument number:

-

Resulting argument: $operandN

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/operator")).should("have.text", "+"); - cy.get(cesc("#\\/numOperands")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/operand1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)"); - }); - cy.get(cesc("#\\/operand2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("g(y,z)"); - }); - cy.get(cesc("#\\/operand3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hq"); - }); - cy.get(cesc("#\\/blank1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f"); - }); - cy.get(cesc("#\\/g")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("g"); - }); - cy.get(cesc("#\\/blank2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/farg1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/farg1a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/blank3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/gargAll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(y,z)"); - }); - cy.get(cesc("#\\/garg1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/garg2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/blank4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/blank5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/numOperands1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/operand11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)"); - }); - cy.get(cesc("#\\/operandN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(x)"); - }); - cy.get(cesc("#\\/functionN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f"); - }); - cy.get(cesc("#\\/argumentN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/operator"].stateValues.value).eq("+"); - expect(stateVariables["/numOperands"].stateValues.value).eq(3); - expect(stateVariables["/operand1"].stateValues.value).eqls([ - "apply", - "f", - "x", - ]); - expect(stateVariables["/operand2"].stateValues.value).eqls([ - "apply", - "g", - ["tuple", "y", "z"], - ]); - expect(stateVariables["/operand3"].stateValues.value).eqls([ - "*", - "h", - "q", - ]); - expect(stateVariables["/blank1"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/f"].stateValues.value).eqls("f"); - expect(stateVariables["/g"].stateValues.value).eqls("g"); - expect(stateVariables["/blank2"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/farg1"].stateValues.value).eqls("x"); - expect(stateVariables["/farg1a"].stateValues.value).eqls("x"); - expect(stateVariables["/blank3"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/gargAll"].stateValues.value).eqls([ - "tuple", - "y", - "z", - ]); - expect(stateVariables["/garg1"].stateValues.value).eqls("y"); - expect(stateVariables["/garg2"].stateValues.value).eqls("z"); - expect(stateVariables["/blank4"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/blank5"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/numOperands1"].stateValues.value).eq(1); - expect(stateVariables["/operand11"].stateValues.value).eqls([ - "apply", - "f", - "x", - ]); - - expect(stateVariables["/operandN"].stateValues.value).eqls([ - "apply", - "f", - "x", - ]); - expect(stateVariables["/functionN"].stateValues.value).eqls("f"); - expect(stateVariables["/argumentN"].stateValues.value).eqls("x"); - }); - - cy.get(cesc("#\\/nArgument") + " textarea") - .type("{end}{backspace}2", { force: true }) - .blur(); - cy.get(cesc("#\\/argumentN") + " .mjx-mrow").should( - "contain.text", - "οΌΏ", - ); - cy.get(cesc("#\\/argumentN")) - .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["/argumentN"].stateValues.value).eqls("οΌΏ"); - }); - - cy.get(cesc("#\\/nOperand") + " textarea") - .type("{end}{backspace}2", { force: true }) - .blur(); - cy.get(cesc("#\\/operandN") + " .mjx-mrow").should( - "contain.text", - "g(y,z)", - ); - cy.get(cesc("#\\/operandN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("g(y,z)"); - }); - cy.get(cesc("#\\/functionN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("g"); - }); - cy.get(cesc("#\\/argumentN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/operandN"].stateValues.value).eqls([ - "apply", - "g", - ["tuple", "y", "z"], - ]); - expect(stateVariables["/functionN"].stateValues.value).eqls("g"); - expect(stateVariables["/argumentN"].stateValues.value).eqls("z"); - }); - - cy.get(cesc("#\\/nArgument") + " textarea") - .type("{end}{backspace}3", { force: true }) - .blur(); - cy.get(cesc("#\\/argumentN") + " .mjx-mrow").should( - "contain.text", - "οΌΏ", - ); - cy.get(cesc("#\\/argumentN")) - .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["/argumentN"].stateValues.value).eqls("οΌΏ"); - }); - - cy.get(cesc("#\\/nArgument") + " textarea") - .type("{end}{backspace}1", { force: true }) - .blur(); - cy.get(cesc("#\\/argumentN") + " .mjx-mrow").should( - "contain.text", - "y", - ); - cy.get(cesc("#\\/argumentN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/argumentN"].stateValues.value).eqls("y"); - }); - - cy.get(cesc("#\\/nOperand") + " textarea") - .type("{end}{backspace}3", { force: true }) - .blur(); - cy.get(cesc("#\\/operandN") + " .mjx-mrow").should( - "contain.text", - "hq", - ); - cy.get(cesc("#\\/operandN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("hq"); - }); - cy.get(cesc("#\\/functionN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/argumentN")) - .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["/operandN"].stateValues.value).eqls([ - "*", - "h", - "q", - ]); - expect(stateVariables["/functionN"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/argumentN"].stateValues.value).eqls("οΌΏ"); - }); - - cy.get(cesc("#\\/nOperand") + " textarea") - .type("{end}{backspace}4", { force: true }) - .blur(); - cy.get(cesc("#\\/operandN") + " .mjx-mrow").should( - "contain.text", - "οΌΏ", - ); - cy.get(cesc("#\\/operandN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/functionN")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("οΌΏ"); - }); - cy.get(cesc("#\\/argumentN")) - .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["/operandN"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/functionN"].stateValues.value).eqls("οΌΏ"); - expect(stateVariables["/argumentN"].stateValues.value).eqls("οΌΏ"); - }); - }); - - it("warning with operand", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

original expression: x+y

-

Bad operand: $expr

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc2("#/operand1") + " .mjx-mrow") - .eq(0) - .should("have.text", "\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( - `Must specify a operandNumber when extracting a math operand`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(23); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(85); - }); - }); - - it("math operators that take multiple inputs ignore composites with no replacements", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (x+1)(x-2)(x-4) -

Min on [0,2]: $$f(0) $(f.minimumValues) $$f(2).

-

Abs treats as product of three factors: $$f(0) $(f.minimumValues) $$f(2).

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/min02")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/abs")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∣∣8οΌΏβ‹…0∣∣"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/min02"].stateValues.value).eq(0); - expect(stateVariables["/abs"].stateValues.value).eqls([ - "apply", - "abs", - ["*", 8, "οΌΏ", 0], - ]); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/number.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/number.cy.js deleted file mode 100644 index 2c2f9085c..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/number.cy.js +++ /dev/null @@ -1,2439 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; - -describe("Number Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("1+1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - $_number1{name="num"} - 1+1 - `, - }, - "*", - ); - }); - - cy.log("Test value displayed in browser"); - cy.get(cesc2("#/num")).should("have.text", "2"); - cy.get(cesc2("#/_number1")).should("have.text", "2"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/num"].stateValues.value).eq(2); - expect(stateVariables["/_number1"].stateValues.value).eq(2); - }); - }); - - it(`number that isn't a number`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - $_number1{name="num"} - x+1 - `, - }, - "*", - ); - }); - - cy.log("Test value displayed in browser"); - cy.get(cesc2("#/num")).should("have.text", "NaN"); - cy.get(cesc2("#/_number1")).should("have.text", "NaN"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - assert.isNaN(stateVariables["/num"].stateValues.value); - assert.isNaN(stateVariables["/_number1"].stateValues.value); - }); - }); - - it(`number becomes non-numeric through inverse`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 5 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n")).should("have.text", "5"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("{end}x{enter}", { - force: true, - }); - cy.get(cesc("#\\/n")).should("have.text", "NaN"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n")).should("have.text", "9"); - }); - - it("number in math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x+3 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+3"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - "x", - 3, - ]); - expect(stateVariables["/_number1"].stateValues.value).to.eq(3); - }); - }); - - it("math in number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 5+3 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_number1")).should("have.text", "8"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).eqls([ - "+", - 5, - 3, - ]); - expect(stateVariables["/_math2"].stateValues.value).eq(3); - expect(stateVariables["/_number1"].stateValues.value).eq(8); - }); - }); - - it("number converts to decimals", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - log(0.5/0.3), - $_number1 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - let num = Math.log(0.5 / 0.3); - let numString = me.math.round(num, 3).toString(); - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_number1")).should("have.text", numString); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(numString); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.value).closeTo( - num, - 1e-14, - ); - expect(stateVariables["/_number1"].stateValues.value).closeTo( - num, - 1e-14, - ); - }); - }); - - it("rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 234234823.34235235324 - 5.4285023408250342 - 0.000000000000005023481340324 - $n1{displayDigits='5' name="n1a"} - $n1{displayDecimals='3' name="n1b"} - $n1{displayDigits='5' displayDecimals='3' displaySmallAsZero="false" name="n1c"} - $n2{displayDigits='5' name="n2a"} - $n2{displayDecimals='3' name="n2b"} - $n2{displayDigits='5' displayDecimals='3' displaySmallAsZero="false" name="n2c"} - $n3{displayDigits='5' name="n3a"} - $n3{displayDecimals='3' name="n3b"} - $n3{displayDigits='5' displayDecimals='3' displaySmallAsZero="false" name="n3c"} - - $n1a{name="n1aa"} - $n1a{displayDecimals='3' name="n1ab"} - $n2a{name="n2aa"} - $n2a{displayDecimals='3' name="n2ab"} - $n3a{displaySmallAsZero="false" name="n3aa"} - $n3a{displayDecimals='3' displaySmallAsZero="false" name="n3ab"} - - $n1b{name="n1ba"} - $n1b{displayDigits='5' name="n1bb"} - $n2b{name="n2ba"} - $n2b{displayDigits='5' name="n2bb"} - $n3b{displaySmallAsZero="false" name="n3ba"} - $n3b{displayDigits='5' displayDecimals='3' displaySmallAsZero="false" name="n3bb"} - - $n1a - $n1b - $n1c - $n2a - $n2b - $n2c - $n3a - $n3b - $n3c - - $n1aa - $n1ab - $n2aa - $n2ab - $n3aa - $n3ab - - $n1ba - $n1bb - $n2ba - $n2bb - $n3ba - $n3bb - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n1")).should("have.text", "234234823.34"); - cy.get(cesc("#\\/n1a")).should("have.text", "234230000"); - cy.get(cesc("#\\/n1b")).should("have.text", "234234823.342"); - cy.get(cesc("#\\/n1c")).should("have.text", "234234823.342"); - cy.get(cesc("#\\/n1am") + " .mjx-mrow") - .eq(0) - .should("have.text", "234230000"); - cy.get(cesc("#\\/n1bm") + " .mjx-mrow") - .eq(0) - .should("have.text", "234234823.342"); - cy.get(cesc("#\\/n1cm") + " .mjx-mrow") - .eq(0) - .should("have.text", "234234823.342"); - - cy.get(cesc("#\\/n2")).should("have.text", "5.43"); - cy.get(cesc("#\\/n2a")).should("have.text", "5.4285"); - cy.get(cesc("#\\/n2b")).should("have.text", "5.429"); - cy.get(cesc("#\\/n2c")).should("have.text", "5.4285"); - cy.get(cesc("#\\/n2am") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.4285"); - cy.get(cesc("#\\/n2bm") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.429"); - cy.get(cesc("#\\/n2cm") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.4285"); - - cy.get(cesc("#\\/n3")).should("have.text", "0"); - cy.get(cesc("#\\/n3a")).should("have.text", "0"); - cy.get(cesc("#\\/n3b")).should("have.text", "0"); - cy.get(cesc("#\\/n3c")).should("have.text", "5.0235 * 10^(-15)"); - cy.get(cesc("#\\/n3am") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n3bm") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n3cm") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.0235β‹…10βˆ’15"); - - cy.get(cesc("#\\/n1aa")).should("have.text", "234230000"); - cy.get(cesc("#\\/n1ab")).should("have.text", "234234823.342"); - cy.get(cesc("#\\/n1aam") + " .mjx-mrow") - .eq(0) - .should("have.text", "234230000"); - cy.get(cesc("#\\/n1abm") + " .mjx-mrow") - .eq(0) - .should("have.text", "234234823.342"); - - cy.get(cesc("#\\/n2aa")).should("have.text", "5.4285"); - cy.get(cesc("#\\/n2ab")).should("have.text", "5.429"); - cy.get(cesc("#\\/n2aam") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.4285"); - cy.get(cesc("#\\/n2abm") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.429"); - - cy.get(cesc("#\\/n3aa")).should("have.text", "5.0235 * 10^(-15)"); - cy.get(cesc("#\\/n3ab")).should("have.text", "0"); - cy.get(cesc("#\\/n3aam") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.0235β‹…10βˆ’15"); - cy.get(cesc("#\\/n3abm") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - - cy.get(cesc("#\\/n1ba")).should("have.text", "234234823.342"); - cy.get(cesc("#\\/n1bb")).should("have.text", "234230000"); - cy.get(cesc("#\\/n1bam") + " .mjx-mrow") - .eq(0) - .should("have.text", "234234823.342"); - cy.get(cesc("#\\/n1bbm") + " .mjx-mrow") - .eq(0) - .should("have.text", "234230000"); - - cy.get(cesc("#\\/n2ba")).should("have.text", "5.429"); - cy.get(cesc("#\\/n2bb")).should("have.text", "5.4285"); - cy.get(cesc("#\\/n2bam") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.429"); - cy.get(cesc("#\\/n2bbm") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.4285"); - - cy.get(cesc("#\\/n3ba")).should("have.text", "0"); - cy.get(cesc("#\\/n3bb")).should("have.text", "5.0235 * 10^(-15)"); - cy.get(cesc("#\\/n3bam") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n3bbm") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.0235β‹…10βˆ’15"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n1"].stateValues.value).eq( - 234234823.34235235324, - ); - expect(stateVariables["/n1a"].stateValues.value).eq( - 234234823.34235235324, - ); - expect(stateVariables["/n1b"].stateValues.value).eq( - 234234823.34235235324, - ); - expect(stateVariables["/n1c"].stateValues.value).eq( - 234234823.34235235324, - ); - expect( - stateVariables[ - stateVariables["/n1am"].activeChildren[0].componentName - ].stateValues.value, - ).eq(234234823.34235235324); - expect( - stateVariables[ - stateVariables["/n1bm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(234234823.34235235324); - expect( - stateVariables[ - stateVariables["/n1cm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(234234823.34235235324); - expect(stateVariables["/n2"].stateValues.value).eq( - 5.4285023408250342, - ); - expect(stateVariables["/n2a"].stateValues.value).eq( - 5.4285023408250342, - ); - expect(stateVariables["/n2b"].stateValues.value).eq( - 5.4285023408250342, - ); - expect(stateVariables["/n2c"].stateValues.value).eq( - 5.4285023408250342, - ); - expect( - stateVariables[ - stateVariables["/n2am"].activeChildren[0].componentName - ].stateValues.value, - ).eq(5.4285023408250342); - expect( - stateVariables[ - stateVariables["/n2bm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(5.4285023408250342); - expect( - stateVariables[ - stateVariables["/n2cm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(5.4285023408250342); - expect(stateVariables["/n3"].stateValues.value).eq( - 0.000000000000005023481340324, - ); - expect(stateVariables["/n3a"].stateValues.value).eq( - 0.000000000000005023481340324, - ); - expect(stateVariables["/n3b"].stateValues.value).eq( - 0.000000000000005023481340324, - ); - expect(stateVariables["/n3c"].stateValues.value).eq( - 0.000000000000005023481340324, - ); - expect( - stateVariables[ - stateVariables["/n3am"].activeChildren[0].componentName - ].stateValues.value, - ).eq(0.000000000000005023481340324); - expect( - stateVariables[ - stateVariables["/n3bm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(0.000000000000005023481340324); - expect( - stateVariables[ - stateVariables["/n3cm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(0.000000000000005023481340324); - - expect(stateVariables["/n1aa"].stateValues.value).eq( - 234234823.34235235324, - ); - expect(stateVariables["/n1ab"].stateValues.value).eq( - 234234823.34235235324, - ); - expect( - stateVariables[ - stateVariables["/n1aam"].activeChildren[0].componentName - ].stateValues.value, - ).eq(234234823.34235235324); - expect( - stateVariables[ - stateVariables["/n1abm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(234234823.34235235324); - expect(stateVariables["/n2aa"].stateValues.value).eq( - 5.4285023408250342, - ); - expect(stateVariables["/n2ab"].stateValues.value).eq( - 5.4285023408250342, - ); - expect( - stateVariables[ - stateVariables["/n2aam"].activeChildren[0].componentName - ].stateValues.value, - ).eq(5.4285023408250342); - expect( - stateVariables[ - stateVariables["/n2abm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(5.4285023408250342); - expect(stateVariables["/n3aa"].stateValues.value).eq( - 0.000000000000005023481340324, - ); - expect(stateVariables["/n3ab"].stateValues.value).eq( - 0.000000000000005023481340324, - ); - expect( - stateVariables[ - stateVariables["/n3aam"].activeChildren[0].componentName - ].stateValues.value, - ).eq(0.000000000000005023481340324); - expect( - stateVariables[ - stateVariables["/n3abm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(0.000000000000005023481340324); - - expect(stateVariables["/n1ba"].stateValues.value).eq( - 234234823.34235235324, - ); - expect(stateVariables["/n1bb"].stateValues.value).eq( - 234234823.34235235324, - ); - expect( - stateVariables[ - stateVariables["/n1bam"].activeChildren[0].componentName - ].stateValues.value, - ).eq(234234823.34235235324); - expect( - stateVariables[ - stateVariables["/n1bbm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(234234823.34235235324); - expect(stateVariables["/n2ba"].stateValues.value).eq( - 5.4285023408250342, - ); - expect(stateVariables["/n2bb"].stateValues.value).eq( - 5.4285023408250342, - ); - expect( - stateVariables[ - stateVariables["/n2bam"].activeChildren[0].componentName - ].stateValues.value, - ).eq(5.4285023408250342); - expect( - stateVariables[ - stateVariables["/n2bbm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(5.4285023408250342); - expect(stateVariables["/n3ba"].stateValues.value).eq( - 0.000000000000005023481340324, - ); - expect(stateVariables["/n3bb"].stateValues.value).eq( - 0.000000000000005023481340324, - ); - expect( - stateVariables[ - stateVariables["/n3bam"].activeChildren[0].componentName - ].stateValues.value, - ).eq(0.000000000000005023481340324); - expect( - stateVariables[ - stateVariables["/n3bbm"].activeChildren[0].componentName - ].stateValues.value, - ).eq(0.000000000000005023481340324); - }); - }); - - it("pad zeros with rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 22 - 0.000000000000005 - $n1{displayDigits='4' name="n1a"} - $n1{displayDigits='4' name="n1apad" padZeros} - $n1{displayDecimals='3' name="n1b"} - $n1{displayDecimals='3' name="n1bpad" padZeros} - $n1{displayDigits='4' displaySmallAsZero name="n1c"} - $n1{displayDigits='4' displaySmallAsZero name="n1cpad" padZeros} - $n2{displayDigits='4' name="n2a"} - $n2{displayDigits='4' name="n2apad" padZeros} - $n2{displayDecimals='3' name="n2b"} - $n2{displayDecimals='3' name="n2bpad" padZeros} - $n2{displayDigits='4' displaySmallAsZero name="n2c"} - $n2{displayDigits='4' displaySmallAsZero name="n2cpad" padZeros} - - $n1a - $n1apad - $n1b - $n1bpad - $n1c - $n1cpad - $n2a - $n2apad - $n2b - $n2bpad - $n2c - $n2cpad - - $n1a - $n1apad - $n1b - $n1bpad - $n1c - $n1cpad - $n2a - $n2apad - $n2b - $n2bpad - $n2c - $n2cpad - - $n1a - $n1apad - $n1b - $n1bpad - $n1c - $n1cpad - $n2a - $n2apad - $n2b - $n2bpad - $n2c - $n2cpad - - $n1a.value{assignNames="n1aValue"} - $n1apad.value{assignNames="n1apadValue"} - $n1b.value{assignNames="n1bValue"} - $n1bpad.value{assignNames="n1bpadValue"} - $n1c.value{assignNames="n1cValue"} - $n1cpad.value{assignNames="n1cpadValue"} - $n2a.value{assignNames="n2aValue"} - $n2apad.value{assignNames="n2apadValue"} - $n2b.value{assignNames="n2bValue"} - $n2bpad.value{assignNames="n2bpadValue"} - $n2c.value{assignNames="n2cValue"} - $n2cpad.value{assignNames="n2cpadValue"} - - $n1a.text{assignNames="n1aText"} - $n1apad.text{assignNames="n1apadText"} - $n1b.text{assignNames="n1bText"} - $n1bpad.text{assignNames="n1bpadText"} - $n1c.text{assignNames="n1cText"} - $n1cpad.text{assignNames="n1cpadText"} - $n2a.text{assignNames="n2aText"} - $n2apad.text{assignNames="n2apadText"} - $n2b.text{assignNames="n2bText"} - $n2bpad.text{assignNames="n2bpadText"} - $n2c.text{assignNames="n2cText"} - $n2cpad.text{assignNames="n2cpadText"} - - $n1a.math{assignNames="n1aMath2"} - $n1apad.math{assignNames="n1apadMath2"} - $n1b.math{assignNames="n1bMath2"} - $n1bpad.math{assignNames="n1bpadMath2"} - $n1c.math{assignNames="n1cMath2"} - $n1cpad.math{assignNames="n1cpadMath2"} - $n2a.math{assignNames="n2aMath2"} - $n2apad.math{assignNames="n2apadMath2"} - $n2b.math{assignNames="n2bMath2"} - $n2bpad.math{assignNames="n2bpadMath2"} - $n2c.math{assignNames="n2cMath2"} - $n2cpad.math{assignNames="n2cpadMath2"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n1")).should("have.text", "22"); - cy.get(cesc("#\\/n1a")).should("have.text", "22"); - cy.get(cesc("#\\/n1apad")).should("have.text", "22.00"); - cy.get(cesc("#\\/n1b")).should("have.text", "22"); - cy.get(cesc("#\\/n1bpad")).should("have.text", "22.000"); - cy.get(cesc("#\\/n1c")).should("have.text", "22"); - cy.get(cesc("#\\/n1cpad")).should("have.text", "22.00"); - cy.get(cesc("#\\/n2")).should("have.text", "5 * 10^(-15)"); - cy.get(cesc("#\\/n2a")).should("have.text", "5 * 10^(-15)"); - cy.get(cesc("#\\/n2apad")).should("have.text", "5.000 * 10^(-15)"); - cy.get(cesc("#\\/n2b")).should("have.text", "0"); - cy.get(cesc("#\\/n2bpad")).should("have.text", "0.000"); - cy.get(cesc("#\\/n2c")).should("have.text", "0"); - cy.get(cesc("#\\/n2cpad")).should("have.text", "0.000"); - - cy.get(cesc("#\\/n1am") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1apadm") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.00"); - cy.get(cesc("#\\/n1bm") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1bpadm") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.000"); - cy.get(cesc("#\\/n1cm") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1cpadm") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.00"); - cy.get(cesc("#\\/n2am") + " .mjx-mrow") - .eq(0) - .should("have.text", "5β‹…10βˆ’15"); - cy.get(cesc("#\\/n2apadm") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.000β‹…10βˆ’15"); - cy.get(cesc("#\\/n2bm") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n2bpadm") + " .mjx-mrow") - .eq(0) - .should("have.text", "0.000"); - cy.get(cesc("#\\/n2cm") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n2cpadm") + " .mjx-mrow") - .eq(0) - .should("have.text", "0.000"); - - cy.get(cesc("#\\/n1aNumber")).should("have.text", "22"); - cy.get(cesc("#\\/n1apadNumber")).should("have.text", "22.00"); - cy.get(cesc("#\\/n1bNumber")).should("have.text", "22"); - cy.get(cesc("#\\/n1bpadNumber")).should("have.text", "22.000"); - cy.get(cesc("#\\/n1cNumber")).should("have.text", "22"); - cy.get(cesc("#\\/n1cpadNumber")).should("have.text", "22.00"); - cy.get(cesc("#\\/n2aNumber")).should("have.text", "5 * 10^(-15)"); - cy.get(cesc("#\\/n2apadNumber")).should( - "have.text", - "5.000 * 10^(-15)", - ); - cy.get(cesc("#\\/n2bNumber")).should("have.text", "0"); - cy.get(cesc("#\\/n2bpadNumber")).should("have.text", "0.000"); - cy.get(cesc("#\\/n2cNumber")).should("have.text", "0"); - cy.get(cesc("#\\/n2cpadNumber")).should("have.text", "0.000"); - - cy.get(cesc("#\\/n1aMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1apadMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.00"); - cy.get(cesc("#\\/n1bMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1bpadMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.000"); - cy.get(cesc("#\\/n1cMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1cpadMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.00"); - cy.get(cesc("#\\/n2aMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "5β‹…10βˆ’15"); - cy.get(cesc("#\\/n2apadMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.000β‹…10βˆ’15"); - cy.get(cesc("#\\/n2bMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n2bpadMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "0.000"); - cy.get(cesc("#\\/n2cMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n2cpadMath") + " .mjx-mrow") - .eq(0) - .should("have.text", "0.000"); - - cy.get(cesc("#\\/n1aValue")).should("have.text", "22"); - cy.get(cesc("#\\/n1apadValue")).should("have.text", "22.00"); - cy.get(cesc("#\\/n1bValue")).should("have.text", "22"); - cy.get(cesc("#\\/n1bpadValue")).should("have.text", "22.000"); - cy.get(cesc("#\\/n1cValue")).should("have.text", "22"); - cy.get(cesc("#\\/n1cpadValue")).should("have.text", "22.00"); - cy.get(cesc("#\\/n2aValue")).should("have.text", "5 * 10^(-15)"); - cy.get(cesc("#\\/n2apadValue")).should("have.text", "5.000 * 10^(-15)"); - cy.get(cesc("#\\/n2bValue")).should("have.text", "0"); - cy.get(cesc("#\\/n2bpadValue")).should("have.text", "0.000"); - cy.get(cesc("#\\/n2cValue")).should("have.text", "0"); - cy.get(cesc("#\\/n2cpadValue")).should("have.text", "0.000"); - - cy.get(cesc("#\\/n1aText")).should("have.text", "22"); - cy.get(cesc("#\\/n1apadText")).should("have.text", "22.00"); - cy.get(cesc("#\\/n1bText")).should("have.text", "22"); - cy.get(cesc("#\\/n1bpadText")).should("have.text", "22.000"); - cy.get(cesc("#\\/n1cText")).should("have.text", "22"); - cy.get(cesc("#\\/n1cpadText")).should("have.text", "22.00"); - cy.get(cesc("#\\/n2aText")).should("have.text", "5 * 10^(-15)"); - cy.get(cesc("#\\/n2apadText")).should("have.text", "5.000 * 10^(-15)"); - cy.get(cesc("#\\/n2bText")).should("have.text", "0"); - cy.get(cesc("#\\/n2bpadText")).should("have.text", "0.000"); - cy.get(cesc("#\\/n2cText")).should("have.text", "0"); - cy.get(cesc("#\\/n2cpadText")).should("have.text", "0.000"); - - cy.get(cesc("#\\/n1aMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1apadMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.00"); - cy.get(cesc("#\\/n1bMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1bpadMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.000"); - cy.get(cesc("#\\/n1cMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "22"); - cy.get(cesc("#\\/n1cpadMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "22.00"); - cy.get(cesc("#\\/n2aMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "5β‹…10βˆ’15"); - cy.get(cesc("#\\/n2apadMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "5.000β‹…10βˆ’15"); - cy.get(cesc("#\\/n2bMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n2bpadMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "0.000"); - cy.get(cesc("#\\/n2cMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc("#\\/n2cpadMath2") + " .mjx-mrow") - .eq(0) - .should("have.text", "0.000"); - }); - - it("dynamic rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number: 35203423.02352343201

-

Number of digits:

-

Number of decimals:

-

$n{displayDigits='$ndigits' displayDecimals='$ndecimals' name="na"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n")).should("have.text", "35203423.02"); - cy.get(cesc("#\\/na")).should("have.text", "35203423.024"); - - cy.log("only digits"); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}-\\infty{enter}{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/na")).should("have.text", "35200000"); - - cy.log("more digits"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}12{enter}", - { force: true }, - ); - cy.get(cesc("#\\/na")).should("have.text", "35203423.0235"); - - cy.log("remove digits"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc("#\\/na")).should("contain.text", "35203423.02352343"); - - cy.log("Fewer digits than have"); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}10{enter}", - { force: true }, - ); - cy.get(cesc("#\\/na")).should("contain.text", "0"); - - cy.log("add one digit"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/na")).should("have.text", "40000000"); - - cy.log("invalid precision means no rounding"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}{backspace}{backspace}y{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/na")).should("contain.text", "35203423.02352343"); - - cy.log("add a decimal"); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/na")).should("have.text", "35203423"); - - cy.log("negative precision, ignores display digits"); - cy.get(cesc("#\\/ndigits") + " textarea").type( - "{end}{backspace}-3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/ndecimals") + " textarea").type( - "{end}{backspace}-3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/na")).should("have.text", "35203000"); - }); - - it("infinity and nan", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - Infinity - Infinity+Infinity - 1/0 - -2/-0 - Infinity - Infinity+Infinity - 5/0 - -6/-0 - - -Infinity - -3/0 - 4/-0 - -Infinity - -8/0 - 7/-0 - - Infinity-Infinity - Infinity/Infinity - 0/0 - -0/0 - -Infinity+Infinity - Infinity/Infinity - 0/0 - 0/-0 - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/inf1")).should("have.text", "∞"); - cy.get(cesc("#\\/inf2")).should("have.text", "∞"); - cy.get(cesc("#\\/inf3")).should("have.text", "∞"); - cy.get(cesc("#\\/inf4")).should("have.text", "∞"); - cy.get(cesc("#\\/inf5")).should("have.text", "∞"); - cy.get(cesc("#\\/inf6")).should("have.text", "∞"); - cy.get(cesc("#\\/inf7")).should("have.text", "∞"); - cy.get(cesc("#\\/inf8")).should("have.text", "∞"); - - cy.get(cesc("#\\/ninf1")).should("have.text", "-∞"); - cy.get(cesc("#\\/ninf2")).should("have.text", "-∞"); - cy.get(cesc("#\\/ninf3")).should("have.text", "-∞"); - cy.get(cesc("#\\/ninf4")).should("have.text", "-∞"); - cy.get(cesc("#\\/ninf5")).should("have.text", "-∞"); - cy.get(cesc("#\\/ninf6")).should("have.text", "-∞"); - - cy.get(cesc("#\\/nan1")).should("have.text", "NaN"); - cy.get(cesc("#\\/nan2")).should("have.text", "NaN"); - cy.get(cesc("#\\/nan3")).should("have.text", "NaN"); - cy.get(cesc("#\\/nan4")).should("have.text", "NaN"); - cy.get(cesc("#\\/nan5")).should("have.text", "NaN"); - cy.get(cesc("#\\/nan6")).should("have.text", "NaN"); - cy.get(cesc("#\\/nan7")).should("have.text", "NaN"); - cy.get(cesc("#\\/nan8")).should("have.text", "NaN"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/inf1"].stateValues.value).eq(Infinity); - expect(stateVariables["/inf2"].stateValues.value).eq(Infinity); - expect(stateVariables["/inf3"].stateValues.value).eq(Infinity); - expect(stateVariables["/inf4"].stateValues.value).eq(Infinity); - expect(stateVariables["/inf5"].stateValues.value).eq(Infinity); - expect(stateVariables["/inf6"].stateValues.value).eq(Infinity); - expect(stateVariables["/inf7"].stateValues.value).eq(Infinity); - expect(stateVariables["/inf8"].stateValues.value).eq(Infinity); - - expect(stateVariables["/ninf1"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf2"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf3"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf4"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf5"].stateValues.value).eq(-Infinity); - expect(stateVariables["/ninf6"].stateValues.value).eq(-Infinity); - - expect(stateVariables["/nan1"].stateValues.value).eqls(NaN); - expect(stateVariables["/nan2"].stateValues.value).eqls(NaN); - expect(stateVariables["/nan3"].stateValues.value).eqls(NaN); - expect(stateVariables["/nan4"].stateValues.value).eqls(NaN); - expect(stateVariables["/nan5"].stateValues.value).eqls(NaN); - expect(stateVariables["/nan6"].stateValues.value).eqls(NaN); - expect(stateVariables["/nan7"].stateValues.value).eqls(NaN); - expect(stateVariables["/nan8"].stateValues.value).eqls(NaN); - }); - }); - - it("copy value prop copies attributes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

8.5203845251 - $n1.value{assignNames="n1a"} - $n1.value{displayDigits="5" assignNames="n1b"} - $n1.value{link="false" assignNames="n1c"} - $n1.value{link="false" displayDigits="5" assignNames="n1d"} -

- -

8.5203845251 - $n2.value{assignNames="n2a"} - $n2.value{displayDecimals="6" assignNames="n2b"} - $n2.value{link="false" assignNames="n2c"} - $n2.value{link="false" displayDecimals="6" assignNames="n2d"} -

- -

0.000000000000000015382487 - $n3.value{assignNames="n3a"} - $n3.value{displaySmallAsZero assignNames="n3b"} - $n3.value{link="false" assignNames="n3c"} - $n3.value{link="false" displaySmallAsZero assignNames="n3d"} -

- -

8 - $n4.value{assignNames="n4a"} - $n4.value{padZeros="false" assignNames="n4b"} - $n4.value{link="false" assignNames="n4c"} - $n4.value{link="false" padZeros="false" assignNames="n4d"} -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n1")).should("have.text", "8.5"); - cy.get(cesc("#\\/n1a")).should("have.text", "8.5"); - cy.get(cesc("#\\/n1b")).should("have.text", "8.5204"); - cy.get(cesc("#\\/n1c")).should("have.text", "8.5"); - cy.get(cesc("#\\/n1d")).should("have.text", "8.5204"); - - cy.get(cesc("#\\/n2")).should("have.text", "9"); - cy.get(cesc("#\\/n2a")).should("have.text", "9"); - cy.get(cesc("#\\/n2b")).should("have.text", "8.520385"); - cy.get(cesc("#\\/n2c")).should("have.text", "9"); - cy.get(cesc("#\\/n2d")).should("have.text", "8.520385"); - - cy.get(cesc("#\\/n3")).should("have.text", "1.54 * 10^(-17)"); - cy.get(cesc("#\\/n3a")).should("have.text", "1.54 * 10^(-17)"); - cy.get(cesc("#\\/n3b")).should("have.text", "0"); - cy.get(cesc("#\\/n3c")).should("have.text", "1.54 * 10^(-17)"); - cy.get(cesc("#\\/n3d")).should("have.text", "0"); - - cy.get(cesc("#\\/n4")).should("have.text", "8.00"); - cy.get(cesc("#\\/n4a")).should("have.text", "8.00"); - cy.get(cesc("#\\/n4b")).should("have.text", "8"); - cy.get(cesc("#\\/n4c")).should("have.text", "8.00"); - cy.get(cesc("#\\/n4d")).should("have.text", "8"); - }); - - it("display rounding preserved when only one number or math child", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

8.5203845251 - 8.5203845251 - 8.52038452512.8392634947 - 8.52038452512.8392634947 - 8.52038452512.8392634947 - 8.52038452512.8392634947 - 8.5203845251 - 8.5203845251 -

- -

- - - - - - - -

- -

8.5203845251 - 8.5203845251 - 8.52038452512.8392634947 - 8.52038452512.8392634947 - 8.52038452512.8392634947 - 8.52038452512.8392634947 - 8.5203845251 - 8.5203845251 -

- -

- - - - - - - -

- -

0.000000000000000015382487 - 0.000000000000000015382487 - 0.0000000000000000153824872.8392634947 - 0.0000000000000000153824872.8392634947 - 0.0000000000000000153824872.8392634947 - 0.0000000000000000153824872.8392634947 - 0.000000000000000015382487 -

- -

- - - - - - -

- -

8 - 8 - 82 - 82 - 82 - 82 - 8 -

- -

- - - - - - -

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/m1")).should("have.text", "8.5"); - cy.get(cesc("#\\/m1a")).should("have.text", "8.5"); - cy.get(cesc("#\\/m1b")).should("have.text", "24.19"); - cy.get(cesc("#\\/m1c")).should("have.text", "24.19"); - cy.get(cesc("#\\/m1d")).should("have.text", "24.19"); - cy.get(cesc("#\\/m1e")).should("have.text", "24.19"); - cy.get(cesc("#\\/m1f")).should("have.text", "9"); - cy.get(cesc("#\\/m1g")).should("have.text", "8.52038453"); - - cy.get(cesc("#\\/m1_v")).should("have.text", "8.5"); - cy.get(cesc("#\\/m1a_v")).should("have.text", "8.5"); - cy.get(cesc("#\\/m1b_v")).should("have.text", "24.19"); - cy.get(cesc("#\\/m1c_v")).should("have.text", "24.19"); - cy.get(cesc("#\\/m1d_v")).should("have.text", "24.19"); - cy.get(cesc("#\\/m1e_v")).should("have.text", "24.19"); - cy.get(cesc("#\\/m1f_v")).should("have.text", "9"); - cy.get(cesc("#\\/m1g_v")).should("have.text", "8.52038453"); - - cy.get(cesc("#\\/m2")).should("have.text", "8.5204"); - cy.get(cesc("#\\/m2a")).should("have.text", "8.5204"); - cy.get(cesc("#\\/m2b")).should("have.text", "24.19"); - cy.get(cesc("#\\/m2c")).should("have.text", "24.19"); - cy.get(cesc("#\\/m2d")).should("have.text", "24.19"); - cy.get(cesc("#\\/m2e")).should("have.text", "24.19"); - cy.get(cesc("#\\/m2f")).should("have.text", "8.520385"); - cy.get(cesc("#\\/m2g")).should("have.text", "8.5203845"); - - cy.get(cesc("#\\/m2_v")).should("have.text", "8.5204"); - cy.get(cesc("#\\/m2a_v")).should("have.text", "8.5204"); - cy.get(cesc("#\\/m2b_v")).should("have.text", "24.19"); - cy.get(cesc("#\\/m2c_v")).should("have.text", "24.19"); - cy.get(cesc("#\\/m2d_v")).should("have.text", "24.19"); - cy.get(cesc("#\\/m2e_v")).should("have.text", "24.19"); - cy.get(cesc("#\\/m2f_v")).should("have.text", "8.520385"); - cy.get(cesc("#\\/m2g_v")).should("have.text", "8.5203845"); - - cy.get(cesc("#\\/m3")).should("have.text", "1.54 * 10^(-17)"); - cy.get(cesc("#\\/m3a")).should("have.text", "1.54 * 10^(-17)"); - cy.get(cesc("#\\/m3b")).should("have.text", "0"); - cy.get(cesc("#\\/m3c")).should("have.text", "0"); - cy.get(cesc("#\\/m3d")).should("have.text", "0"); - cy.get(cesc("#\\/m3e")).should("have.text", "0"); - cy.get(cesc("#\\/m3f")).should("have.text", "1.54 * 10^(-17)"); - - cy.get(cesc("#\\/m3_v")).should("have.text", "1.54 * 10^(-17)"); - cy.get(cesc("#\\/m3a_v")).should("have.text", "1.54 * 10^(-17)"); - cy.get(cesc("#\\/m3b_v")).should("have.text", "0"); - cy.get(cesc("#\\/m3c_v")).should("have.text", "0"); - cy.get(cesc("#\\/m3d_v")).should("have.text", "0"); - cy.get(cesc("#\\/m3e_v")).should("have.text", "0"); - cy.get(cesc("#\\/m3f_v")).should("have.text", "1.54 * 10^(-17)"); - - cy.get(cesc("#\\/m4")).should("have.text", "8.00"); - cy.get(cesc("#\\/m4a")).should("have.text", "8.00"); - cy.get(cesc("#\\/m4b")).should("have.text", "16"); - cy.get(cesc("#\\/m4c")).should("have.text", "16"); - cy.get(cesc("#\\/m4d")).should("have.text", "16"); - cy.get(cesc("#\\/m4e")).should("have.text", "16"); - cy.get(cesc("#\\/m4f")).should("have.text", "8"); - - cy.get(cesc("#\\/m4_v")).should("have.text", "8.00"); - cy.get(cesc("#\\/m4a_v")).should("have.text", "8.00"); - cy.get(cesc("#\\/m4b_v")).should("have.text", "16"); - cy.get(cesc("#\\/m4c_v")).should("have.text", "16"); - cy.get(cesc("#\\/m4d_v")).should("have.text", "16"); - cy.get(cesc("#\\/m4e_v")).should("have.text", "16"); - cy.get(cesc("#\\/m4f_v")).should("have.text", "8"); - }); - - it("value on NaN", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- -

- - $mi1 -

- -

- - $mi2 -

- -

- - -

- -

- - -

- - -

- - $mi1a -

- -

- - $mi2a -

- -

- - $mi2b -

- -

- - -

- -

- - -

- -

- - -

- - -

- 8/ - 8/ -

- -

- - $b>y - $b>y -

- -

- x>y - x>y -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc("#\\/n1")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc("#\\/n2")).should("have.text", "3"); - - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "NaN", - ); - }); - cy.get(cesc("#\\/n3")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi4`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - cy.get(cesc("#\\/n4")).should("have.text", "5"); - - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc("#\\/n1a")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi2a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc("#\\/n2a")).should("have.text", "3"); - - cy.get(cesc(`#\\/mi3a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc("#\\/n3a")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi4a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - cy.get(cesc("#\\/n4a")).should("have.text", "5"); - - cy.get(cesc(`#\\/mi2b`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc("#\\/n2b")).should("have.text", "3"); - - cy.get(cesc(`#\\/mi4b`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - cy.get(cesc("#\\/n4b")).should("have.text", "5"); - - cy.get(cesc("#\\/n5")).should("have.text", "NaN"); - cy.get(cesc("#\\/n6")).should("have.text", "7"); - - cy.get(cesc("#\\/n7")).should("have.text", "NaN"); - cy.get(cesc("#\\/n8")).should("have.text", "9"); - - cy.get(cesc("#\\/n9")).should("have.text", "NaN"); - cy.get(cesc("#\\/n10")).should("have.text", "-9"); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi4") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mi1a") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2a") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3a") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi4a") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mi2b") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi4b") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}3/4{enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/mi4b`) + ` .mq-editable-field`).should( - "contain.text", - "0.75", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "34", - ); - }); - cy.get(cesc("#\\/n1")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "34", - ); - }); - cy.get(cesc("#\\/n2")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "0.75", - ); - }); - cy.get(cesc("#\\/n3")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi4`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "0.75", - ); - }); - cy.get(cesc("#\\/n4")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "34", - ); - }); - cy.get(cesc("#\\/n1a")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi2a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "34", - ); - }); - cy.get(cesc("#\\/n2a")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi3a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "0.75", - ); - }); - cy.get(cesc("#\\/n3a")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi4a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "0.75", - ); - }); - cy.get(cesc("#\\/n4a")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi2b`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "34", - ); - }); - cy.get(cesc("#\\/n2b")).should("have.text", "0.75"); - - cy.get(cesc(`#\\/mi4b`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "0.75", - ); - }); - cy.get(cesc("#\\/n4b")).should("have.text", "0.75"); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi4") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mi1a") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2a") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3a") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi4a") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/mi2b") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi4b") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}x{enter}", - { force: true }, - ); - - cy.get(cesc(`#\\/mi4b`) + ` .mq-editable-field`).should( - "contain.text", - "5", - ); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc("#\\/n1")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc("#\\/n2")).should("have.text", "3"); - - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "NaN", - ); - }); - cy.get(cesc("#\\/n3")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi4`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - cy.get(cesc("#\\/n4")).should("have.text", "5"); - - cy.get(cesc(`#\\/mi1a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc("#\\/n1a")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi2a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc("#\\/n2a")).should("have.text", "3"); - - cy.get(cesc(`#\\/mi3a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(""); - }); - cy.get(cesc("#\\/n3a")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi4a`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - cy.get(cesc("#\\/n4a")).should("have.text", "5"); - - cy.get(cesc(`#\\/mi2b`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x"); - }); - cy.get(cesc("#\\/n2b")).should("have.text", "3"); - - cy.get(cesc(`#\\/mi4b`) + ` .mq-editable-field`) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("5"); - }); - cy.get(cesc("#\\/n4b")).should("have.text", "5"); - }); - - it("indeterminant forms give NaN", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- -

0^0

-

Infinity^0

-

0/0

-

Infinity/Infinity

-

0*Infinity

-

Infinity-Infinity

-

1^Infinity

-

0^0^0

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/if1")).should("have.text", "NaN"); - cy.get(cesc("#\\/if2")).should("have.text", "NaN"); - cy.get(cesc("#\\/if3")).should("have.text", "NaN"); - cy.get(cesc("#\\/if4")).should("have.text", "NaN"); - cy.get(cesc("#\\/if5")).should("have.text", "NaN"); - cy.get(cesc("#\\/if6")).should("have.text", "NaN"); - cy.get(cesc("#\\/if7")).should("have.text", "NaN"); - cy.get(cesc("#\\/ifalt")).should("have.text", "NaN"); - }); - - it("complex numbers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- -

i

-

$i1

-

sqrt(-1)

-

exp(pi i/2)

-

$ni1^3

-

$ni2^3

-

$ni3^3

-

1/-i

-

1/$ni4

-

1/$ni5

-

1/$ni6

-

0+i

-

1i

- -

-i

-

$ni1

-

i^3

-

(-1)^(3/2)

-

exp(3 pi i/2)

-

$i1^3

-

$i2^3

-

$i3^3

-

1/i

-

1/$i4

-

1/$i5

-

1/$i6

-

0-i

-

-1i

- -

2+3i

-

2+3i

-

(2+3i)/(3+i)

-

2+3i/3+i

-

Infinity i

-

\\infty i

-

5+0i

-

5+0i

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/i1")).should("have.text", "i"); - cy.get(cesc("#\\/i1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "i"); - cy.get(cesc("#\\/i2")).should("have.text", "i"); - cy.get(cesc("#\\/i3")).should("have.text", "i"); - cy.get(cesc("#\\/i4")).should("have.text", "i"); - cy.get(cesc("#\\/i5")).should("have.text", "i"); - cy.get(cesc("#\\/i6")).should("have.text", "i"); - cy.get(cesc("#\\/i7")).should("have.text", "i"); - cy.get(cesc("#\\/i8")).should("have.text", "i"); - cy.get(cesc("#\\/i9")).should("have.text", "i"); - cy.get(cesc("#\\/i10")).should("have.text", "i"); - cy.get(cesc("#\\/i11")).should("have.text", "i"); - cy.get(cesc("#\\/i12")).should("have.text", "i"); - - cy.get(cesc("#\\/ni1")).should("have.text", "-i"); - cy.get(cesc("#\\/ni1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "βˆ’i"); - cy.get(cesc("#\\/ni2")).should("have.text", "-i"); - cy.get(cesc("#\\/ni3")).should("have.text", "-i"); - cy.get(cesc("#\\/ni4")).should("have.text", "-i"); - cy.get(cesc("#\\/ni5")).should("have.text", "-i"); - cy.get(cesc("#\\/ni6")).should("have.text", "-i"); - cy.get(cesc("#\\/ni7")).should("have.text", "-i"); - cy.get(cesc("#\\/ni8")).should("have.text", "-i"); - cy.get(cesc("#\\/ni9")).should("have.text", "-i"); - cy.get(cesc("#\\/ni10")).should("have.text", "-i"); - cy.get(cesc("#\\/ni11")).should("have.text", "-i"); - cy.get(cesc("#\\/ni12")).should("have.text", "-i"); - cy.get(cesc("#\\/ni13")).should("have.text", "-i"); - - cy.get(cesc("#\\/c1")).should("have.text", "2 + 3 i"); - cy.get(cesc("#\\/c2")).should("have.text", "2 + 3 i"); - cy.get(cesc("#\\/c3")).should("have.text", "0.9 + 0.7 i"); - cy.get(cesc("#\\/c4")).should("have.text", "0.9 + 0.7 i"); - cy.get(cesc("#\\/c5")).should("have.text", "NaN + NaN i"); - cy.get(cesc("#\\/c6")).should("have.text", "NaN + NaN i"); - cy.get(cesc("#\\/c7")).should("have.text", "5"); - cy.get(cesc("#\\/c8")).should("have.text", "5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/i1"].stateValues.value).eqls({ - re: 0, - im: 1, - }); - expect(stateVariables["/i1a"].stateValues.value).eqls("i"); - expect(stateVariables["/i2"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/i2"].stateValues.value.im).eq(1); - expect(stateVariables["/i3"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/i3"].stateValues.value.im).eq(1); - expect(stateVariables["/i4"].stateValues.value.re).eq(0); - expect(stateVariables["/i4"].stateValues.value.im).eq(1); - expect(stateVariables["/i5"].stateValues.value.re).eq(0); - expect(stateVariables["/i5"].stateValues.value.im).eq(1); - expect(stateVariables["/i6"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/i6"].stateValues.value.im).eq(1); - expect(stateVariables["/i7"].stateValues.value.re).eq(0); - expect(stateVariables["/i7"].stateValues.value.im).eq(1); - expect(stateVariables["/i8"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/i8"].stateValues.value.im).eq(1); - expect(stateVariables["/i9"].stateValues.value.re).eq(0); - expect(stateVariables["/i9"].stateValues.value.im).eq(1); - expect(stateVariables["/i10"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/i10"].stateValues.value.im).eq(1); - expect(stateVariables["/i11"].stateValues.value.re).eq(0); - expect(stateVariables["/i11"].stateValues.value.im).eq(1); - expect(stateVariables["/i12"].stateValues.value.re).eq(0); - expect(stateVariables["/i12"].stateValues.value.im).eq(1); - - expect(stateVariables["/ni1"].stateValues.value.re).eq(0); - expect(stateVariables["/ni1"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni1a"].stateValues.value).eqls(["-", "i"]); - expect(stateVariables["/ni2"].stateValues.value.re).eq(0); - expect(stateVariables["/ni2"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni3"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/ni3"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni4"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/ni4"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni5"].stateValues.value.re).eq(0); - expect(stateVariables["/ni5"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni6"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/ni6"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni7"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/ni7"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni8"].stateValues.value.re).eq(0); - expect(stateVariables["/ni8"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni9"].stateValues.value.re).eq(0); - expect(stateVariables["/ni9"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni10"].stateValues.value.re).eq(0); - expect(stateVariables["/ni10"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni11"].stateValues.value.re).closeTo( - 0, - 1e-14, - ); - expect(stateVariables["/ni11"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni12"].stateValues.value.re).eq(0); - expect(stateVariables["/ni12"].stateValues.value.im).eq(-1); - expect(stateVariables["/ni13"].stateValues.value.re).eq(0); - expect(stateVariables["/ni13"].stateValues.value.im).eq(-1); - - expect(stateVariables["/c1"].stateValues.value.re).eq(2); - expect(stateVariables["/c1"].stateValues.value.im).eq(3); - expect(stateVariables["/c2"].stateValues.value.re).eq(2); - expect(stateVariables["/c2"].stateValues.value.im).eq(3); - expect(stateVariables["/c3"].stateValues.value.re).closeTo( - 0.9, - 1e-14, - ); - expect(stateVariables["/c3"].stateValues.value.im).closeTo( - 0.7, - 1e-14, - ); - expect(stateVariables["/c4"].stateValues.value.re).closeTo( - 0.9, - 1e-14, - ); - expect(stateVariables["/c4"].stateValues.value.im).closeTo( - 0.7, - 1e-14, - ); - expect(stateVariables["/c5"].stateValues.value.re).eqls(NaN); - expect(stateVariables["/c5"].stateValues.value.im).eqls(NaN); - expect(stateVariables["/c6"].stateValues.value.re).eqls(NaN); - expect(stateVariables["/c6"].stateValues.value.im).eqls(NaN); - expect(stateVariables["/c7"].stateValues.value).eq(5); - expect(stateVariables["/c8"].stateValues.value).eq(5); - }); - }); - - it("complex numbers and inverse definition", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

-

1

-

1

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n1")).should("have.text", "1"); - cy.get(cesc("#\\/n2")).should("have.text", "1"); - cy.get(cesc("#\\/n3")).should("have.text", "NaN"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "have.text", - "1", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "have.text", - "1", - ); - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`).should("have.text", ""); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n1"].stateValues.value).eqls(1); - expect(stateVariables["/n2"].stateValues.value).eqls(1); - expect(stateVariables["/n3"].stateValues.value).eqls(NaN); - expect(stateVariables["/mi1"].stateValues.value).eqls(1); - expect(stateVariables["/mi2"].stateValues.value).eqls(1); - expect(stateVariables["/mi3"].stateValues.value).eqls(NaN); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type("{end}{backspace}i{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi2") + " textarea").type("{end}{backspace}i{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi3") + " textarea") - .type("{end}{backspace}i{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/n1")).should("have.text", "i"); - cy.get(cesc("#\\/n2")).should("have.text", "i"); - cy.get(cesc("#\\/n3")).should("have.text", "i"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "have.text", - "i", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "have.text", - "i", - ); - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`).should( - "have.text", - "i", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n1"].stateValues.value).eqls({ - re: 0, - im: 1, - }); - expect(stateVariables["/n2"].stateValues.value).eqls({ - re: 0, - im: 1, - }); - expect(stateVariables["/n3"].stateValues.value).eqls({ - re: 0, - im: 1, - }); - expect(stateVariables["/mi1"].stateValues.value).eqls("i"); - expect(stateVariables["/mi2"].stateValues.value).eqls("i"); - expect(stateVariables["/mi3"].stateValues.value).eqls("i"); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type("{end}+2{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi2") + " textarea").type("{end}+2{enter}", { - force: true, - }); - cy.get(cesc("#\\/mi3") + " textarea") - .type("{end}+2{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/n1")).should("have.text", "2 + i"); - cy.get(cesc("#\\/n2")).should("have.text", "2 + i"); - cy.get(cesc("#\\/n3")).should("have.text", "2 + i"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "have.text", - "2+i", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "have.text", - "2+i", - ); - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`).should( - "have.text", - "2+i", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n1"].stateValues.value.re).eq(2); - expect(stateVariables["/n1"].stateValues.value.im).eq(1); - expect(stateVariables["/n2"].stateValues.value.re).eq(2); - expect(stateVariables["/n2"].stateValues.value.im).eq(1); - expect(stateVariables["/n3"].stateValues.value.re).eq(2); - expect(stateVariables["/n3"].stateValues.value.im).eq(1); - expect(stateVariables["/mi1"].stateValues.value).eqls([ - "+", - 2, - "i", - ]); - expect(stateVariables["/mi2"].stateValues.value).eqls([ - "+", - 2, - "i", - ]); - expect(stateVariables["/mi3"].stateValues.value).eqls([ - "+", - 2, - "i", - ]); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{end}{backspace}{backspace}{backspace}3+0i{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi2") + " textarea").type( - "{end}{backspace}{backspace}{backspace}3+0i{enter}", - { force: true }, - ); - cy.get(cesc("#\\/mi3") + " textarea") - .type("{end}{backspace}{backspace}{backspace}3+0i{enter}", { - force: true, - }) - .blur(); - - cy.get(cesc("#\\/n1")).should("have.text", "3"); - cy.get(cesc("#\\/n2")).should("have.text", "3"); - cy.get(cesc("#\\/n3")).should("have.text", "3"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "have.text", - "3", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "have.text", - "3", - ); - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`).should( - "have.text", - "3", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n1"].stateValues.value).eq(3); - expect(stateVariables["/n2"].stateValues.value).eq(3); - expect(stateVariables["/n3"].stateValues.value).eq(3); - expect(stateVariables["/mi1"].stateValues.value).eqls(3); - expect(stateVariables["/mi2"].stateValues.value).eqls(3); - expect(stateVariables["/mi3"].stateValues.value).eqls(3); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{end}{backspace}1i{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mi2") + " textarea").type( - "{end}{backspace}1i{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mi3") + " textarea") - .type("{end}{backspace}1i{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/n1")).should("have.text", "i"); - cy.get(cesc("#\\/n2")).should("have.text", "i"); - cy.get(cesc("#\\/n3")).should("have.text", "i"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "have.text", - "i", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "have.text", - "i", - ); - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`).should( - "have.text", - "i", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n1"].stateValues.value).eqls({ - re: 0, - im: 1, - }); - expect(stateVariables["/n2"].stateValues.value).eqls({ - re: 0, - im: 1, - }); - expect(stateVariables["/n3"].stateValues.value).eqls({ - re: 0, - im: 1, - }); - expect(stateVariables["/mi1"].stateValues.value).eqls("i"); - expect(stateVariables["/mi2"].stateValues.value).eqls("i"); - expect(stateVariables["/mi3"].stateValues.value).eqls("i"); - }); - - cy.get(cesc("#\\/mi1") + " textarea").type( - "{end}{backspace}-1i+0{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mi2") + " textarea").type( - "{end}{backspace}-1i+0{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/mi3") + " textarea") - .type("{end}{backspace}-1i+0{enter}", { force: true }) - .blur(); - - cy.get(cesc("#\\/n1")).should("have.text", "-i"); - cy.get(cesc("#\\/n2")).should("have.text", "-i"); - cy.get(cesc("#\\/n3")).should("have.text", "-i"); - - cy.get(cesc(`#\\/mi1`) + ` .mq-editable-field`).should( - "have.text", - "βˆ’i", - ); - cy.get(cesc(`#\\/mi2`) + ` .mq-editable-field`).should( - "have.text", - "βˆ’i", - ); - cy.get(cesc(`#\\/mi3`) + ` .mq-editable-field`).should( - "have.text", - "βˆ’i", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n1"].stateValues.value.re).eq(0); - expect(stateVariables["/n1"].stateValues.value.im).eq(-1); - expect(stateVariables["/n2"].stateValues.value.re).eq(0); - expect(stateVariables["/n2"].stateValues.value.im).eq(-1); - expect(stateVariables["/n3"].stateValues.value.re).eq(0); - expect(stateVariables["/n3"].stateValues.value.im).eq(-1); - expect(stateVariables["/mi1"].stateValues.value).eqls(["-", "i"]); - expect(stateVariables["/mi2"].stateValues.value).eqls(["-", "i"]); - expect(stateVariables["/mi3"].stateValues.value).eqls(["-", "i"]); - }); - }); - - it("complex numbers, re and im", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

a

- -

re(2-4i)

-

im(2-4i)

-

re((2-4i)(3-i))

-

im((2-4i)(3-i))

-

re(2-4i)

-

im(2-4i)

-

re((2-4i)(3-i))

-

im((2-4i)(3-i))

-

\\Re(2-4i)

-

\\Im(2-4i)

-

\\Re((2-4i)(3-i))

-

\\Im((2-4i)(3-i))

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n1")).should("have.text", "2"); - cy.get(cesc("#\\/n2")).should("have.text", "-4"); - cy.get(cesc("#\\/n3")).should("have.text", "2"); - cy.get(cesc("#\\/n4")).should("have.text", "-14"); - cy.get(cesc("#\\/n1a")).should("have.text", "2"); - cy.get(cesc("#\\/n2a")).should("have.text", "-4"); - cy.get(cesc("#\\/n3a")).should("have.text", "2"); - cy.get(cesc("#\\/n4a")).should("have.text", "-14"); - cy.get(cesc("#\\/n1b")).should("have.text", "2"); - cy.get(cesc("#\\/n2b")).should("have.text", "-4"); - cy.get(cesc("#\\/n3b")).should("have.text", "2"); - cy.get(cesc("#\\/n4b")).should("have.text", "-14"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n1"].stateValues.value).eq(2); - expect(stateVariables["/n2"].stateValues.value).eq(-4); - expect(stateVariables["/n3"].stateValues.value).eq(2); - expect(stateVariables["/n4"].stateValues.value).eq(-14); - expect(stateVariables["/n1a"].stateValues.value).eq(2); - expect(stateVariables["/n2a"].stateValues.value).eq(-4); - expect(stateVariables["/n3a"].stateValues.value).eq(2); - expect(stateVariables["/n4a"].stateValues.value).eq(-14); - expect(stateVariables["/n1b"].stateValues.value).eq(2); - expect(stateVariables["/n2b"].stateValues.value).eq(-4); - expect(stateVariables["/n3b"].stateValues.value).eq(2); - expect(stateVariables["/n4b"].stateValues.value).eq(-14); - }); - }); - - it("number in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $content1 - -17 - - -

Anchor 1 coordinates: $number1.anchor

-

Anchor 2 coordinates: $number2.anchor

-

Change anchor 1 coordinates:

-

Change anchor 2 coordinates:

-

Position from anchor 1: $number1.positionFromAnchor

-

Position from anchor 2: $number2.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

-

Content 1: $number1

-

Content 2: $number2

-

Content 1

-

Content 2

-

- - `, - }, - "*", - ); - }); - - 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.get(cesc("#\\/pContent1")).should("have.text", "Content 1: 11"); - cy.get(cesc("#\\/pContent2")).should("have.text", "Content 2: -17"); - - cy.log("move numbers by dragging"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveNumber", - componentName: "/number1", - args: { x: -2, y: 3 }, - }); - win.callAction1({ - actionName: "moveNumber", - componentName: "/number2", - 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 numbers 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 numbers by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveNumber", - componentName: "/number1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveNumber", - componentName: "/number2", - 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("change content of number"); - cy.get(cesc("#\\/content1") + " textarea").type("{end}+5{enter}", { - force: true, - }); - cy.get(cesc("#\\/content2") + " textarea").type("{end}-1{enter}", { - force: true, - }); - - cy.get(cesc("#\\/pContent2")).should("have.text", "Content 2: -18"); - cy.get(cesc("#\\/pContent1")).should("have.text", "Content 1: 16"); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/p.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/p.cy.js deleted file mode 100644 index a4b601e8e..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/p.cy.js +++ /dev/null @@ -1,72 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("P Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("two paragraphs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Hello, paragraph 1

-

Bye, paragraph 2

- `, - }, - "*", - ); - }); - - cy.log("find paragraphs"); - cy.get("p" + cesc("#\\/_p1")).should("have.text", "Hello, paragraph 1"); - cy.get("p" + cesc("#\\/_p2")).should("have.text", "Bye, paragraph 2"); - }); - - it("paragraph with math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

math in paragraph: x+x

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("find mathjax rendered math in paragraph"); - cy.get("p" + cesc("#\\/_p1")) - .find(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - }); - - it("spaces preserved between tags", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hello x

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get("p" + cesc("#\\/_p1")) - .invoke("text") - .should("contain", "Hello x"); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/polygon.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/polygon.cy.js index 4bff9ce66..f51526465 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/polygon.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/polygon.cy.js @@ -1,139 +1,4 @@ -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); - } -} - -async function testPolygonCopiedTwice({ - vertices, - polygonName = "/pg", - graph1Name = "/g1", - graph2Name = "/g2", - graph3Name = "/g3", - pointsInDomPrefix = "/p", -}) { - for (let i in vertices) { - let ind = Number(i) + 1; - if (Number.isFinite(vertices[i][0])) { - cy.get(`#${cesc2(pointsInDomPrefix + ind)} .mjx-mrow`).should( - "contain.text", - `(${nInDOM( - Math.round(vertices[i][0] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - } - if (Number.isFinite(vertices[i][1])) { - cy.get(`#${cesc2(pointsInDomPrefix + ind)} .mjx-mrow`).should( - "contain.text", - `,${nInDOM( - Math.round(vertices[i][1] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - } - } - cy.get(`#${cesc2(pointsInDomPrefix + (vertices.length + 1))}`).should( - "not.exist", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[graph1Name + polygonName].stateValues.numVertices, - ).eqls(vertices.length); - expect( - stateVariables[graph2Name + polygonName].stateValues.numVertices, - ).eqls(vertices.length); - expect( - stateVariables[graph3Name + polygonName].stateValues.numVertices, - ).eqls(vertices.length); - - for (let i in vertices) { - if (Number.isFinite(vertices[i][0])) { - expect( - me - .fromAst( - stateVariables[graph1Name + polygonName].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - expect( - me - .fromAst( - stateVariables[graph2Name + polygonName].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - expect( - me - .fromAst( - stateVariables[graph3Name + polygonName].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - } else { - expect( - stateVariables[graph1Name + polygonName].stateValues - .vertices[i][0], - ).eq(vertices[i][0]); - expect( - stateVariables[graph2Name + polygonName].stateValues - .vertices[i][0], - ).eq(vertices[i][0]); - expect( - stateVariables[graph3Name + polygonName].stateValues - .vertices[i][0], - ).eq(vertices[i][0]); - } - if (Number.isFinite(vertices[i][1])) { - expect( - me - .fromAst( - stateVariables[graph1Name + polygonName].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - expect( - me - .fromAst( - stateVariables[graph2Name + polygonName].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - expect( - me - .fromAst( - stateVariables[graph3Name + polygonName].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - } else { - expect( - stateVariables[graph1Name + polygonName].stateValues - .vertices[i][1], - ).eq(vertices[i][1]); - expect( - stateVariables[graph2Name + polygonName].stateValues - .vertices[i][1], - ).eq(vertices[i][1]); - expect( - stateVariables[graph3Name + polygonName].stateValues - .vertices[i][1], - ).eq(vertices[i][1]); - } - } - }); -} +import { cesc } from "@doenet/utils"; describe("Polygon Tag Tests", function () { beforeEach(() => { @@ -141,8255 +6,839 @@ describe("Polygon Tag Tests", function () { cy.visit("/"); }); - it("Polygon vertices and copied points", () => { + it("style description changes with theme", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - - (3,5) - (-4,-1) - (5,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, + + + + + + + + + + + +

Polygon A is $A.styleDescription.

+

B is a $B.styleDescriptionWithNoun.

+

C is a $C.styleDescriptionWithNoun.

+

A has a $A.borderStyleDescription border.

+

B has a $B.borderStyleDescription border.

+

C has a $C.borderStyleDescription border.

+

A has a $A.fillStyleDescription fill.

+

B has a $B.fillStyleDescription fill.

+

C has a $C.fillStyleDescription fill.

+ `, }, "*", ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - let vertices = [ - [3, 5], - [-4, -1], - [5, 2], - [-3, 4], - ]; + cy.get(cesc("#\\/Adescrip")).should( + "have.text", + "Polygon A is filled brown with thick border.", + ); + cy.get(cesc("#\\/Bdescrip")).should( + "have.text", + "B is a filled dark red polygon.", + ); + cy.get(cesc("#\\/Cdescrip")).should( + "have.text", + "C is a filled black polygon with a thin border.", + ); + cy.get(cesc("#\\/Aborderdescrip")).should( + "have.text", + "A has a thick brown border.", + ); + cy.get(cesc("#\\/Bborderdescrip")).should( + "have.text", + "B has a dark red border.", + ); + cy.get(cesc("#\\/Cborderdescrip")).should( + "have.text", + "C has a thin black border.", + ); + cy.get(cesc("#\\/Afilldescrip")).should( + "have.text", + "A has a brown fill.", + ); + cy.get(cesc("#\\/Bfilldescrip")).should( + "have.text", + "B has a dark red fill.", + ); + cy.get(cesc("#\\/Cfilldescrip")).should( + "have.text", + "C has a black fill.", + ); - testPolygonCopiedTwice({ vertices }); + cy.log("set dark mode"); + cy.get("#testRunner_toggleControls").click(); + cy.get("#testRunner_darkMode").click(); + cy.wait(100); + cy.get("#testRunner_toggleControls").click(); - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; + cy.get(cesc("#\\/Adescrip")).should( + "have.text", + "Polygon A is filled yellow with thick border.", + ); + cy.get(cesc("#\\/Bdescrip")).should( + "have.text", + "B is a filled light red polygon.", + ); + cy.get(cesc("#\\/Cdescrip")).should( + "have.text", + "C is a filled white polygon with a thin border.", + ); + cy.get(cesc("#\\/Aborderdescrip")).should( + "have.text", + "A has a thick yellow border.", + ); + cy.get(cesc("#\\/Bborderdescrip")).should( + "have.text", + "B has a light red border.", + ); + cy.get(cesc("#\\/Cborderdescrip")).should( + "have.text", + "C has a thin white border.", + ); + cy.get(cesc("#\\/Afilldescrip")).should( + "have.text", + "A has a yellow fill.", + ); + cy.get(cesc("#\\/Bfilldescrip")).should( + "have.text", + "B has a light red fill.", + ); + cy.get(cesc("#\\/Cfilldescrip")).should( + "have.text", + "C has a white fill.", + ); + }); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); + // it("Rigid polygon, vertex constraint", () => { + // cy.window().then(async (win) => { + // win.postMessage( + // { + // doenetML: ` + // a + // + // (3,7) + // (-4,-1) + // (8,2) + // (-3,4) - testPolygonCopiedTwice({ vertices }); - }); + // (1,9) + // + // + // $a1 + // + // + // + // + // $(../g1/pg{name="pg"}) + // + // $g2{name="g3"} + // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) + // `, + // }, + // "*", + // ); + // }); + // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - cy.log("move copied polygon up and to the right"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; + // let vertices = [ + // [3, 7], + // [-4, -1], + // [8, 2], + // [-3, 4], + // ]; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } + // let centroid = vertices.reduce( + // (a, c) => [a[0] + c[0], a[1] + c[1]], + // [0, 0], + // ); + // centroid[0] /= 4; + // centroid[1] /= 4; - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); + // testPolygonCopiedTwice({ vertices }); - testPolygonCopiedTwice({ vertices }); - }); + // cy.log("move individual vertex rotates, attracts to point"); + // cy.window().then(async (win) => { + // // rotate by 90 degrees counterclockwise around centroid + // // (shrinking by 1/2, but that will be ignored) + // let requested_vertex_1 = [ + // -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + // 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + // ]; + // vertices = vertices.map((v) => [ + // -(v[1] - centroid[1]) + centroid[0], + // v[0] - centroid[0] + centroid[1], + // ]); + // // since attracted to point, moves down one and to the left + // vertices = vertices.map((v) => [v[0] - 1, v[1] - 1]); - cy.log("move double copied individual vertex"); - cy.window().then(async (win) => { - vertices[2] = [-9, -8]; + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g1/pg", + // args: { + // pointCoords: { 1: requested_vertex_1 }, + // }, + // }); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: vertices[2] }, - }, - }); + // testPolygonCopiedTwice({ vertices }); + // }); - testPolygonCopiedTwice({ vertices }); - }); - }); + // cy.log("rotating further so no attraction preserves old centroid"); + // cy.window().then(async (win) => { + // // location of vertices if weren't attracted to point, moves up one and to the right + // vertices = vertices.map((v) => [v[0] + 1, v[1] + 1]); - it("Polygon string points in vertices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -1 - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load + // // rotate by another 90 degrees counterclockwise around centroid + // // (doubling but that will be ignored) + // let requested_vertex_1 = [ + // -2 * (vertices[1][1] - centroid[1]) + centroid[0], + // 2 * (vertices[1][0] - centroid[0]) + centroid[1], + // ]; + // vertices = vertices.map((v) => [ + // -(v[1] - centroid[1]) + centroid[0], + // v[0] - centroid[0] + centroid[1], + // ]); - let vertices = [ - [3, 5], - [-4, -1], - [5, 2], - [-3, 4], - ]; + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g1/pg", + // args: { + // pointCoords: { 1: requested_vertex_1 }, + // }, + // }); - testPolygonCopiedTwice({ vertices }); + // testPolygonCopiedTwice({ vertices }); + // }); - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; + // cy.log( + // "move copied polygon up and to the left chooses minimum moved and gets attracted", + // ); + // cy.window().then(async (win) => { + // let moveX = -4; + // let moveY = 1; - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); + // // add extra movement to requested vertices, which will be ignored + // let requested_vertices = []; + // for (let i = 0; i < vertices.length; i++) { + // vertices[i][0] = vertices[i][0] + moveX; + // vertices[i][1] = vertices[i][1] + moveY; + // requested_vertices.push([ + // vertices[i][0] - i, + // vertices[i][1] + 2 * i, + // ]); + // } - testPolygonCopiedTwice({ vertices }); - }); + // // since attracted to point, moves up one and to the left + // vertices = vertices.map((v) => [v[0] - 1, v[1] + 1]); - cy.log("move copied polygon up and to the right"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g2/pg", + // args: { + // pointCoords: requested_vertices, + // }, + // }); - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } + // testPolygonCopiedTwice({ vertices }); + // }); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); + // cy.log( + // "move double copied individual vertex, getting rotation around new centroid", + // ); + // cy.window().then(async (win) => { + // let centroid = vertices.reduce( + // (a, c) => [a[0] + c[0], a[1] + c[1]], + // [0, 0], + // ); + // centroid[0] /= 4; + // centroid[1] /= 4; - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move double copied individual vertex"); - cy.window().then(async (win) => { - vertices[2] = [-9, -8]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: vertices[2] }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("dynamic polygon with vertices from copied map, initially zero, copied", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = []; - testPolygonCopiedTwice({ vertices }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}1{enter}", { force: true }) - .then(() => { - vertices[0] = [0, 5 * Math.sin(0)]; - testPolygonCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - vertices[1] = [1, 5 * Math.sin(1)]; - testPolygonCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}3{enter}", { force: true }) - .then(() => { - vertices[2] = [2, 5 * Math.sin(2)]; - testPolygonCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - vertices.splice(2, 1); - testPolygonCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}0{enter}", { force: true }) - .then(() => { - vertices = []; - testPolygonCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}5{enter}", { force: true }) - .then(() => { - for (let i = 0; i < 5; i++) { - vertices.push([i, 5 * Math.sin(i)]); - } - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("start over and begin with big increment"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b - - - - - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "b"); //wait for page to load - - cy.window().then(async (win) => { - vertices = []; - testPolygonCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}10{enter}", { force: true }) - .then(() => { - for (let i = 0; i < 10; i++) { - vertices.push([i, 5 * Math.sin(i)]); - } - testPolygonCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}{backspace}1{enter}", { force: true }) - .then(() => { - vertices = [[0, 5 * Math.sin(0)]]; - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("polygon with initially undefined point", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [1, 2], - [-1, 5], - ["\uff3f", 7], - [3, -5], - [-4, -3], - ]; - testPolygonCopiedTwice({ vertices }); - - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type("{end}{backspace}-2{enter}", { force: true }) - .then(() => { - vertices[2][0] = -2; - testPolygonCopiedTwice({ vertices }); - }); - }); - - it(`can't move polygon based on map`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - - $ti.value{assignNames="t"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = []; - for (let i = -5; i <= 5; i++) { - vertices.push([i, 5 * Math.sin(i)]); - } - testPolygonCopiedTwice({ vertices }); - - cy.log("can't move points"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/mp1", - args: { x: 9, y: -8 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/mp9", - args: { x: -8, y: 4 }, - }); - - // since core could be delayed and we can't tell that no change occurred, - // change value of textinput and wait for the change to be processed by core - cy.get(cesc("#\\/ti_input")).type("wait{enter}"); - cy.get(cesc("#\\/t")) - .should("have.text", "wait") - .then(() => { - testPolygonCopiedTwice({ vertices }); - }); - }); - - cy.log("can't move polygon1"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - let vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: vertices2, - }, - }); - - cy.get(cesc("#\\/ti_input")).clear().type("more{enter}"); - cy.get(cesc("#\\/t")) - .should("have.text", "more") - .then(() => { - testPolygonCopiedTwice({ vertices }); - }); - }); - - cy.log("can't move polygon2"); - cy.window().then(async (win) => { - let moveX = -5; - let moveY = 6; - - let vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices2, - }, - }); - - cy.get(cesc("#\\/ti_input")).clear().type("less{enter}"); - cy.get(cesc("#\\/t")) - .should("have.text", "less") - .then(() => { - testPolygonCopiedTwice({ vertices }); - }); - }); - - cy.log("can't move polygon3"); - cy.window().then(async (win) => { - let moveX = 7; - let moveY = -4; - - let vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: vertices2, - }, - }); - - cy.get(cesc("#\\/ti_input")).clear().type("last{enter}"); - cy.get(cesc("#\\/t")) - .should("have.text", "last") - .then(() => { - testPolygonCopiedTwice({ vertices }); - }); - }); - }); - - it(`create moveable polygon based on map`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - - $ti.value{assignNames="t"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = []; - for (let i = -5; i <= 5; i++) { - vertices.push([i, 5 * Math.sin(i)]); - } - testPolygonCopiedTwice({ vertices }); - - cy.log("can move points"); - - cy.window().then(async (win) => { - vertices[0] = [9, -8]; - vertices[8] = [-8, 4]; - - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/mp1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/mp9", - args: { x: vertices[8][0], y: vertices[8][1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("can move polygon1"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("can move polygon2"); - cy.window().then(async (win) => { - let moveX = -5; - let moveY = 6; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("can move polygon3"); - cy.window().then(async (win) => { - let moveX = 7; - let moveY = -4; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("copy vertices of polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_polygon1.vertex1{assignNames="v1"} - $_polygon1.vertex2{assignNames="v2"} - $_polygon1.vertex3{assignNames="v3"} - $_polygon1.vertex4{assignNames="v4"} - - - - - $_polygon1.vertex4{assignNames="v4b"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let ps = [ - [-3, -1], - [1, 2], - [3, 4], - [6, -2], - ]; - - for (let i = 0; i < 4; i++) { - expect(stateVariables[`/v${i + 1}`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}`].stateValues.xs[1]).eq( - ps[i][1], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1]).eq( - ps[i][1], - ); - } - - cy.get(cesc("#\\/v4b") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(ps[3][0])},${nInDOM(ps[3][1])})`, - ); - }); - - cy.log("move individually copied vertices"); - cy.window().then(async (win) => { - let ps = [ - [-5, 3], - [-2, 7], - [0, -8], - [9, -6], - ]; - - for (let i = 0; i < 4; i++) { - win.callAction1({ - actionName: "movePoint", - componentName: `/v${i + 1}`, - args: { x: ps[i][0], y: ps[i][1] }, - }); - } - - cy.get(cesc("#\\/v4b") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(ps[3][0])},${nInDOM(ps[3][1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 0; i < 4; i++) { - expect(stateVariables[`/v${i + 1}`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}`].stateValues.xs[1]).eq( - ps[i][1], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1]).eq( - ps[i][1], - ); - } - }); - }); - - cy.log("move array-copied vertices"); - cy.window().then(async (win) => { - let ps = [ - [-7, -1], - [-3, 5], - [2, 4], - [6, 0], - ]; - - for (let i = 0; i < 4; i++) { - win.callAction1({ - actionName: "movePoint", - componentName: `/v${i + 1}a`, - args: { x: ps[i][0], y: ps[i][1] }, - }); - } - - cy.get(cesc("#\\/v4b") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(ps[3][0])},${nInDOM(ps[3][1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 0; i < 4; i++) { - expect(stateVariables[`/v${i + 1}`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}`].stateValues.xs[1]).eq( - ps[i][1], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1]).eq( - ps[i][1], - ); - } - }); - }); - }); - - it("new polygon from copied vertices of polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [-9, 6], - [-3, 7], - [4, 0], - [8, 5], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move first polygon up and to the right"); - cy.window().then(async (win) => { - let moveX = 4; - let moveY = 2; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the left"); - cy.window().then(async (win) => { - let moveX = -7; - let moveY = 3; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move dobule copied polygon down and to the left"); - cy.window().then(async (win) => { - let moveX = -1; - let moveY = -4; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("new polygon as translated version of polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - $_polygon1.vertices{name="vs"} - - - - - $_polygon2.vertices{assignNames="p1 p2 p3 p4"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - async function testPolygons({ vertices, transX, transY }) { - let vertices2 = vertices.map((v) => [v[0] + transX, v[1] + transY]); - - for (let i in vertices) { - let ind = Number(i) + 1; - cy.get(`#${cesc2("/p" + ind)} .mjx-mrow`).should( - "contain.text", - `(${nInDOM( - Math.round(vertices2[i][0] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - cy.get(`#${cesc2("/p" + ind)} .mjx-mrow`).should( - "contain.text", - `,${nInDOM( - Math.round(vertices2[i][1] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - } - cy.get(`#${cesc2("/p" + (vertices.length + 1))}`).should( - "not.exist", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.numVertices, - ).eqls(vertices.length); - expect( - stateVariables["/_polygon2"].stateValues.numVertices, - ).eqls(vertices.length); - - for (let i in vertices) { - if (Number.isFinite(vertices[i][0])) { - expect( - me - .fromAst( - stateVariables["/_polygon1"].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - expect( - me - .fromAst( - stateVariables["/_polygon2"].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices2[i][0], 1e-12); - } else { - expect( - stateVariables["/_polygon1"].stateValues.vertices[ - i - ][0], - ).eq(vertices[i][0]); - expect( - stateVariables["/_polygon2"].stateValues.vertices[ - i - ][0], - ).eq(vertices2[i][0]); - } - if (Number.isFinite(vertices[i][1])) { - expect( - me - .fromAst( - stateVariables["/_polygon1"].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - expect( - me - .fromAst( - stateVariables["/_polygon2"].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices2[i][1], 1e-12); - } else { - expect( - stateVariables["/_polygon1"].stateValues.vertices[ - i - ][1], - ).eq(vertices[i][1]); - expect( - stateVariables["/_polygon2"].stateValues.vertices[ - i - ][1], - ).eq(vertices2[i][1]); - } - } - }); - } - - let vertices = [ - [0, 0], - [3, -4], - [1, -6], - [-5, -6], - ]; - let transX = 5; - let transY = 7; - - testPolygons({ vertices, transX, transY }); - - cy.log("move points on first polygon"); - cy.window().then(async (win) => { - vertices = [ - [1, -1], - [-3, 2], - [-1, 7], - [6, 3], - ]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: vertices, - }, - }); - - testPolygons({ vertices, transX, transY }); - }); - - cy.log("move points on second polygon"); - cy.window().then(async (win) => { - let vertices2 = [ - [-3, 4], - [1, 0], - [9, 6], - [2, -1], - ]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon2", - args: { - pointCoords: vertices2, - }, - }); - - vertices = vertices2.map((v) => [v[0] - transX, v[1] - transY]); - - testPolygons({ vertices, transX, transY }); - }); - - cy.log("change translation"); - cy.get(cesc("#\\/transx") + " textarea").type( - "{end}{backspace}2{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/transy") + " textarea").type( - "{end}{backspace}10{enter}", - { - force: true, - }, - ); - cy.window().then(async (win) => { - transX = 2; - transY = 10; - - testPolygons({ vertices, transX, transY }); - }); - }); - - it("parallelogram based on three points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $parallelogram.vertices{assignNames="p1 p2 p3 p4"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - let D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/parallelogram", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/parallelogram", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/parallelogram", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - D = [7, 0]; - B = [A[0] + C[0] - D[0], A[1] + C[1] - D[1]]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/parallelogram", - args: { - pointCoords: { 3: D }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - }); - }); - - it("new polygon from copied vertices, some flipped", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $_polygon2.vertices{assignNames="p1 p2 p3 p4"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - async function testPolygons({ vertices }) { - let vertices2 = [...vertices]; - vertices2[1] = [vertices2[1][1], vertices2[1][0]]; - vertices2[3] = [vertices2[3][1], vertices2[3][0]]; - - for (let i in vertices) { - let ind = Number(i) + 1; - cy.get(`#${cesc2("/p" + ind)} .mjx-mrow`).should( - "contain.text", - `(${nInDOM( - Math.round(vertices2[i][0] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - cy.get(`#${cesc2("/p" + ind)} .mjx-mrow`).should( - "contain.text", - `,${nInDOM( - Math.round(vertices2[i][1] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - } - cy.get(`#${cesc2("/p" + (vertices.length + 1))}`).should( - "not.exist", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.numVertices, - ).eqls(vertices.length); - expect( - stateVariables["/_polygon2"].stateValues.numVertices, - ).eqls(vertices.length); - - for (let i in vertices) { - if (Number.isFinite(vertices[i][0])) { - expect( - me - .fromAst( - stateVariables["/_polygon1"].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - expect( - me - .fromAst( - stateVariables["/_polygon2"].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices2[i][0], 1e-12); - } else { - expect( - stateVariables["/_polygon1"].stateValues.vertices[ - i - ][0], - ).eq(vertices[i][0]); - expect( - stateVariables["/_polygon2"].stateValues.vertices[ - i - ][0], - ).eq(vertices2[i][0]); - } - if (Number.isFinite(vertices[i][1])) { - expect( - me - .fromAst( - stateVariables["/_polygon1"].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - expect( - me - .fromAst( - stateVariables["/_polygon2"].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices2[i][1], 1e-12); - } else { - expect( - stateVariables["/_polygon1"].stateValues.vertices[ - i - ][1], - ).eq(vertices[i][1]); - expect( - stateVariables["/_polygon2"].stateValues.vertices[ - i - ][1], - ).eq(vertices2[i][1]); - } - } - }); - } - - let vertices = [ - [-9, 6], - [-3, 7], - [4, 0], - [8, 5], - ]; - - testPolygons({ vertices }); - - cy.log("move first polygon verticies"); - cy.window().then(async (win) => { - vertices = [ - [7, 2], - [1, -3], - [2, 9], - [-4, -3], - ]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: vertices, - }, - }); - - testPolygons({ vertices }); - }); - - cy.log("move second polygon verticies"); - cy.window().then(async (win) => { - let vertices2 = [ - [-1, 9], - [5, 7], - [-8, 1], - [-7, 6], - ]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon2", - args: { - pointCoords: vertices2, - }, - }); - - vertices = [...vertices2]; - vertices[1] = [vertices[1][1], vertices[1][0]]; - vertices[3] = [vertices[3][1], vertices[3][0]]; - - testPolygons({ vertices }); - }); - }); - - it("four vertex polygon based on three points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_polygon1.vertices{assignNames="p1 p2 p3 p4"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - let D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_polygon1"].stateValues.vertices[0]).eqls( - A, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[1]).eqls( - B, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[2]).eqls( - C, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[3]).eqls( - D, - ); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - D = [7, 0]; - A = [C[0] + B[0] - D[0], C[1] + B[1] - D[1]]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 3: D }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(D); - }); - }); - }); - - it("fourth vertex depends on internal copy of first vertex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_polygon1.vertices{assignNames="p1 p2 p3 p4"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_polygon1"].stateValues.numVertices).eq(4); - expect(stateVariables["/_polygon1"].stateValues.vertices[0]).eqls( - A, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[1]).eqls( - B, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[2]).eqls( - C, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[3]).eqls( - A, - ); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 3: A }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - }); - - it("first vertex depends on internal copy of fourth vertex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_polygon1.vertices{assignNames="p1 p2 p3 p4"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_polygon1"].stateValues.numVertices).eq(4); - expect(stateVariables["/_polygon1"].stateValues.vertices[0]).eqls( - A, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[1]).eqls( - B, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[2]).eqls( - C, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[3]).eqls( - A, - ); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 3: A }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - }); - - it("first vertex depends fourth, formula for fifth", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_polygon1.vertices{assignNames="p1 p2 p3 p4 p5"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - let D = [A[0] + 1, 2]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_polygon1"].stateValues.vertices[0]).eqls( - A, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[1]).eqls( - B, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[2]).eqls( - C, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[3]).eqls( - A, - ); - expect(stateVariables["/_polygon1"].stateValues.vertices[4]).eqls( - D, - ); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - D[0] = A[0] + 1; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - D[0] = A[0] + 1; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 3: A }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - - cy.log("move fifth vertex"); - cy.window().then(async (win) => { - D = [-5, 9]; - A[0] = D[0] - 1; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 4: D }, - }, - }); - - cy.get(cesc("#\\/p5") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polygon1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polygon1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polygon1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polygon1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - }); - - it("first, fourth, seventh vertex depends on fourth, seventh, tenth", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $P.vertices{assignNames="p1 p2 p3 p4 p5 p6 p7 p8 p9 p10"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [-5, -1]; - let B = [1, 2]; - let C = [3, 4]; - let D = [5, 7]; - let E = [-5, 7]; - let F = [3, 1]; - let G = [5, 0]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -9]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 3: A }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move fifth vertex"); - cy.window().then(async (win) => { - D = [-9, 1]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 4: D }, - }, - }); - - cy.get(cesc("#\\/p5") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move sixth vertex"); - cy.window().then(async (win) => { - E = [-3, 6]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 5: E }, - }, - }); - - cy.get(cesc("#\\/p6") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(E[0])},${nInDOM(E[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move seventh vertex"); - cy.window().then(async (win) => { - A = [2, -4]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 6: A }, - }, - }); - - cy.get(cesc("#\\/p7") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move eighth vertex"); - cy.window().then(async (win) => { - F = [6, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 7: F }, - }, - }); - - cy.get(cesc("#\\/p8") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(F[0])},${nInDOM(F[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move nineth vertex"); - cy.window().then(async (win) => { - G = [1, -8]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 8: G }, - }, - }); - - cy.get(cesc("#\\/p9") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(G[0])},${nInDOM(G[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move tenth vertex"); - cy.window().then(async (win) => { - A = [-6, 10]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 9: A }, - }, - }); - - cy.get(cesc("#\\/p10") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - }); - - it("first, fourth, seventh vertex depends on shifted fourth, seventh, tenth", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $P.vertices{assignNames="p1 p2 p3 p4 p5 p6 p7 p8 p9 p10"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [-5, -1]; - let B = [1, 2]; - let C = [3, 4]; - let D = [5, 7]; - let E = [-5, 7]; - let F = [3, 1]; - let G = [5, 0]; - let A1 = [A[0] + 1, A[1] + 1]; - let A2 = [A[0] + 2, A[1] + 2]; - let A3 = [A[0] + 3, A[1] + 3]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A3[0])},${nInDOM(A3[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -9]; - A1 = [A[0] + 1, A[1] + 1]; - A2 = [A[0] + 2, A[1] + 2]; - A3 = [A[0] + 3, A[1] + 3]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 0: A3 }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A3[0])},${nInDOM(A3[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - A1 = [A[0] + 1, A[1] + 1]; - A2 = [A[0] + 2, A[1] + 2]; - A3 = [A[0] + 3, A[1] + 3]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 3: A2 }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A2[0])},${nInDOM(A2[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move fifth vertex"); - cy.window().then(async (win) => { - D = [-9, 1]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 4: D }, - }, - }); - - cy.get(cesc("#\\/p5") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move sixth vertex"); - cy.window().then(async (win) => { - E = [-3, 6]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 5: E }, - }, - }); - - cy.get(cesc("#\\/p6") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(E[0])},${nInDOM(E[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move seventh vertex"); - cy.window().then(async (win) => { - A = [2, -4]; - A1 = [A[0] + 1, A[1] + 1]; - A2 = [A[0] + 2, A[1] + 2]; - A3 = [A[0] + 3, A[1] + 3]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 6: A1 }, - }, - }); - - cy.get(cesc("#\\/p7") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A1[0])},${nInDOM(A1[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move eighth vertex"); - cy.window().then(async (win) => { - F = [6, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 7: F }, - }, - }); - - cy.get(cesc("#\\/p8") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(F[0])},${nInDOM(F[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move nineth vertex"); - cy.window().then(async (win) => { - G = [1, -8]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 8: G }, - }, - }); - - cy.get(cesc("#\\/p9") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(G[0])},${nInDOM(G[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move tenth vertex"); - cy.window().then(async (win) => { - A = [-6, 7]; - A1 = [A[0] + 1, A[1] + 1]; - A2 = [A[0] + 2, A[1] + 2]; - A3 = [A[0] + 3, A[1] + 3]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/P", - args: { - pointCoords: { 9: A }, - }, - }); - - cy.get(cesc("#\\/p10") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - }); - - it("attract to polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_polygon1 - - - - $_point1{name="p1" displayDigits="8"} - $_polygon1.vertices{assignNames="v1 v2 v3" displayDigits="8"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let x1 = 3, - x2 = -4, - x3 = 5; - let y1 = 5, - y2 = -1, - y3 = 2; - - cy.log("point originally not attracted"); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", `(7,8)`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.coords).eqls([ - "vector", - 7, - 8, - ]); - }); - - cy.log("move point near segment 1"); - cy.window().then(async (win) => { - let x = 1; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(1.14`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move point near segment 2"); - cy.window().then(async (win) => { - let x = 3; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.4; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3.12`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - - cy.log("move point near segment between first and last vertices"); - cy.window().then(async (win) => { - let x = 4; - let mseg3 = (y1 - y3) / (x1 - x3); - let y = mseg3 * (x - x3) + y3 + 0.2; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3.90`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); - }); - }); - - cy.log("move point just past first vertex"); - cy.window().then(async (win) => { - let x = x1 + 0.2; - let y = y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3,5)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x1, 1e-6); - expect(py).closeTo(y1, 1e-6); - }); - }); - - cy.log("point not attracted along extension of first segment"); - cy.window().then(async (win) => { - let x = 4; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", `(4,`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-5)},`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.log("move point just past second vertex"); - cy.window().then(async (win) => { - let x = x2 - 0.2; - let y = y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-4)},`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log("point not attracted along extension of second segment"); - cy.window().then(async (win) => { - let x = 6; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", `(6,`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-5)},`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.log("move polygon so point attracts to first segment"); - cy.window().then(async (win) => { - let moveX = -3; - let moveY = -2; - - x1 += moveX; - x2 += moveX; - x3 += moveX; - y1 += moveY; - y2 += moveY; - y3 += moveY; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: [ - [x1, y1], - [x2, y2], - [x3, y3], - ], - }, - }); - - cy.get(cesc("#\\/v1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg1 = (y2 - y1) / (x2 - x1); - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move second vertex so point attracts to second segment"); - cy.window().then(async (win) => { - let moveX = -1; - let moveY = 1; - - x2 += moveX; - y2 += moveY; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 1: [x2, y2] }, - }, - }); - - cy.get(cesc("#\\/v2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg2 = (y2 - y3) / (x2 - x3); - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - }); - - it("constrain to polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_polygon1 - - - - $_point1{name="p1" displayDigits="8"} - $_polygon1.vertices{assignNames="v1 v2 v3" displayDigits="8"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let x1 = 3, - x2 = -4, - x3 = 5; - let y1 = 5, - y2 = -1, - y3 = 2; - - cy.log("point originally constrained"); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${x1},${y1})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - }); - - cy.log("move point near segment 1"); - cy.window().then(async (win) => { - let x = 1; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(1.14`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move point near segment 2"); - cy.window().then(async (win) => { - let x = 3; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.4; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3.12`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - - cy.log("move point near segment between first and last vertices"); - cy.window().then(async (win) => { - let x = 4; - let mseg3 = (y1 - y3) / (x1 - x3); - let y = mseg3 * (x - x3) + y3 + 0.2; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3.90`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); - }); - }); - - cy.log("move point just past first vertex"); - cy.window().then(async (win) => { - let x = x1 + 0.2; - let y = y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3,5)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x1, 1e-6); - expect(py).closeTo(y1, 1e-6); - }); - }); - - cy.log( - "point along extension of first segment constrained to endpoint", - ); - cy.window().then(async (win) => { - let x = 4; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x1, 1e-6); - expect(py).closeTo(y1, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log("move point just past second vertex"); - cy.window().then(async (win) => { - let x = x2 - 0.2; - let y = y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log( - "point along extension of second segment constrained to endpoint", - ); - cy.window().then(async (win) => { - let x = 6; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x3)},${nInDOM(y3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x3, 1e-6); - expect(py).closeTo(y3, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log("move polygon so point constrained to first segment"); - cy.window().then(async (win) => { - let moveX = -3; - let moveY = -5; - - x1 += moveX; - x2 += moveX; - x3 += moveX; - y1 += moveY; - y2 += moveY; - y3 += moveY; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: [ - [x1, y1], - [x2, y2], - [x3, y3], - ], - }, - }); - - cy.get(cesc("#\\/v1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg1 = (y2 - y1) / (x2 - x1); - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move second vertex so point constrained to second segment"); - cy.window().then(async (win) => { - let moveX = -1; - let moveY = 8; - - x2 += moveX; - y2 += moveY; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 1: [x2, y2] }, - }, - }); - - cy.get(cesc("#\\/v2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg2 = (y2 - y3) / (x2 - x3); - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - }); - - it("constrain to polygon, different scales from graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $p - - - - $A{name="A2"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let x1 = -50, - x2 = -40, - x3 = 70, - x4 = 10; - let y1 = -0.02, - y2 = 0.07, - y3 = 0.06, - y4 = -0.01; - - cy.log("point originally on segment 3"); - - cy.get(cesc("#\\/A2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(15)}`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mseg3 = (y4 - y3) / (x4 - x3); - - let px = stateVariables["/A"].stateValues.xs[0]; - let py = stateVariables["/A"].stateValues.xs[1]; - - expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); - }); - - cy.log("move point near segment 1"); - cy.window().then(async (win) => { - let mseg1 = (y2 - y1) / (x2 - x1); - - win.callAction1({ - actionName: "movePoint", - componentName: `/A`, - args: { x: -20, y: 0.02 }, - }); - - cy.get(cesc("#\\/A2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-45)}`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/A"].stateValues.xs[0]; - let py = stateVariables["/A"].stateValues.xs[1]; - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move point near segment 2"); - cy.window().then(async (win) => { - let mseg2 = (y2 - y3) / (x2 - x3); - - win.callAction1({ - actionName: "movePoint", - componentName: `/A`, - args: { x: 0, y: 0.04 }, - }); - - cy.get(cesc("#\\/A2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(2.3)}`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/A"].stateValues.xs[0]; - let py = stateVariables["/A"].stateValues.xs[1]; - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - - cy.log("move point near segment 4"); - cy.window().then(async (win) => { - let mseg4 = (y4 - y1) / (x4 - x1); - - win.callAction1({ - actionName: "movePoint", - componentName: `/A`, - args: { x: -10, y: 0.02 }, - }); - - cy.get(cesc("#\\/A2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-4.5)}`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/A"].stateValues.xs[0]; - let py = stateVariables["/A"].stateValues.xs[1]; - - expect(py).closeTo(mseg4 * (px - x4) + y4, 1e-6); - }); - }); - }); - - it("constrain to interior of polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_polygon1 - - - - $_point1{name="p1" displayDigits="8"} - $_polygon1.vertices{assignNames="v1 v2 v3" displayDigits="8"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let x1 = 3, - x2 = -4, - x3 = 5; - let y1 = 5, - y2 = -1, - y3 = 2; - - cy.log("point originally constrained"); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${x1},${y1})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - }); - - cy.log("move point near segment 1, outside polygon"); - cy.window().then(async (win) => { - let x = 1; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(1.14`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move point near segment 2, but inside polygon"); - cy.window().then(async (win) => { - let x = 3; - let y = 1.5; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3,1.5)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(3, 1e-12); - expect(py).closeTo(1.5, 1e-12); - }); - }); - - cy.log( - "move point near segment between first and last vertices, but outside polygon", - ); - cy.window().then(async (win) => { - let x = 4; - let mseg3 = (y1 - y3) / (x1 - x3); - let y = mseg3 * (x - x3) + y3 + 0.2; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3.90`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); - }); - }); - - cy.log("move point just past first vertex"); - cy.window().then(async (win) => { - let x = x1 + 0.2; - let y = y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3,5)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x1, 1e-6); - expect(py).closeTo(y1, 1e-6); - }); - }); - - cy.log( - "point along extension of first segment constrained to endpoint", - ); - cy.window().then(async (win) => { - let x = 4; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x1, 1e-6); - expect(py).closeTo(y1, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log("move point just past second vertex"); - cy.window().then(async (win) => { - let x = x2 - 0.2; - let y = y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log( - "point along extension of second segment constrained to endpoint", - ); - cy.window().then(async (win) => { - let x = 6; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x3)},${nInDOM(y3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x3, 1e-6); - expect(py).closeTo(y3, 1e-6); - }); - }); - - cy.log("repeat for other side of second segment"); - let xsave, ysave; - cy.window().then(async (win) => { - let x = -5; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - - // save point coordinates, as is last time move point - xsave = x2; - ysave = y2; - }); - - cy.log("move polygon so point constrained to first segment"); - cy.window().then(async (win) => { - let moveX = -3; - let moveY = -5; - - x1 += moveX; - x2 += moveX; - x3 += moveX; - y1 += moveY; - y2 += moveY; - y3 += moveY; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: [ - [x1, y1], - [x2, y2], - [x3, y3], - ], - }, - }); - - cy.get(cesc("#\\/v1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg1 = (y2 - y1) / (x2 - x1); - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move second vertex so point constrained to second segment"); - cy.window().then(async (win) => { - let moveX = -1; - let moveY = 8; - - x2 += moveX; - y2 += moveY; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 1: [x2, y2] }, - }, - }); - - cy.get(cesc("#\\/v2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg2 = (y2 - y3) / (x2 - x3); - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - - cy.log("move third vertex so point is in interior"); - cy.window().then(async (win) => { - x3 = -4; - y3 = -6; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/_polygon1", - args: { - pointCoords: { 2: [x3, y3] }, - }, - }); - - cy.get(cesc("#\\/v3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x3)},${nInDOM(y3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - // point moves to coordinates where last moved the point - expect(px).closeTo(xsave, 1e-6); - expect(py).closeTo(ysave, 1e-6); - }); - }); - }); - - it("constrain to interior of non-simple polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $pg - - - - $P{name="p1" displayDigits="8"} - `, - }, - "*", - ); - }); - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for page to load - - cy.log("point originally in interior"); - - cy.get(cesc2("#/p1") + " .mjx-mrow").should("contain.text", `(7,6)`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/P"].stateValues.xs[0]; - let py = stateVariables["/P"].stateValues.xs[1]; - expect(px).closeTo(7, 1e-12); - expect(py).closeTo(6, 1e-12); - }); - - cy.log("move point above polygon"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: `/P`, - args: { x: 3, y: 10 }, - }); - - cy.get(cesc2("#/p1") + " .mjx-mrow").should( - "contain.text", - `(3,8)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/P"].stateValues.xs[0]; - let py = stateVariables["/P"].stateValues.xs[1]; - expect(px).closeTo(3, 1e-12); - expect(py).closeTo(8, 1e-12); - }); - }); - - cy.log("move point inside doubly wound region"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: `/P`, - args: { x: 3, y: 5 }, - }); - - cy.get(cesc2("#/p1") + " .mjx-mrow").should( - "contain.text", - `(3,5)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/P"].stateValues.xs[0]; - let py = stateVariables["/P"].stateValues.xs[1]; - expect(px).closeTo(3, 1e-12); - expect(py).closeTo(5, 1e-12); - }); - }); - - cy.log("attempt to move point inside zero wound region"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: `/P`, - args: { x: 4.9, y: 3 }, - }); - - cy.get(cesc2("#/p1") + " .mjx-mrow").should( - "contain.text", - `(4,3)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/P"].stateValues.xs[0]; - let py = stateVariables["/P"].stateValues.xs[1]; - expect(px).closeTo(4, 1e-12); - expect(py).closeTo(3, 1e-12); - }); - }); - }); - - it("fixed polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $ti.value{assignNames="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["/p"].stateValues.vertices[0]).eqls([1, 3]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.fixed).eq(true); - }); - - cy.log("cannot move vertices"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: [ - [4, 7], - [8, 10], - [1, 9], - ], - }, - }); - - // to make sure waited for core to react, - // wait for text to change from change in textinput - cy.get(cesc("#\\/ti_input")).type("wait{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "wait"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([ - 1, 3, - ]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([ - 5, 7, - ]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([ - -2, 6, - ]); - }); - }); - }); - - it("copy propIndex of vertices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -

- -

- -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let t1x = 2, - t1y = -3; - let t2x = 3, - t2y = 4; - let t3x = -3, - t3y = 4; - - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t1x)},${nInDOM(t1y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2x)}`, - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t2x)},${nInDOM(t2y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2y)}`, - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t3x)},${nInDOM(t3y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - }); - - it("copy propIndex of vertices, dot and array notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -

- -

- -

- -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let t1x = 2, - t1y = -3; - let t2x = 3, - t2y = 4; - let t3x = -3, - t3y = 4; - - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t1x)},${nInDOM(t1y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2x)}`, - ); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2x)}`, - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t2x)},${nInDOM(t2y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2y)}`, - ); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2y)}`, - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t3x)},${nInDOM(t3y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should("not.exist"); - }); - - it("polygon from vector operations", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (-3,2) - - (2,1) - - - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’3,2)"); - cy.get(cesc2("#/P1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,βˆ’2)"); - cy.get(cesc2("#/P2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,3)"); - cy.get(cesc2("#/P3") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’4,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/polygon"].stateValues.vertices).eqls([ - [7, -2], - [6, 3], - [-4, 5], - ]); - }); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/polygon", - args: { - pointCoords: { 0: [3, 5] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(6,3)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’4,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/polygon"].stateValues.vertices).eqls([ - [3, 5], - [6, 3], - [-4, 5], - ]); - }); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/polygon", - args: { - pointCoords: { 1: [-9, -6] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(βˆ’9,βˆ’6)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’9,2)"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/polygon", - args: { - pointCoords: { 2: [-3, 1] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(9,βˆ’9)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’3,1)"); - }); - - it("polygon from vector operations, create individual vectors", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (-3,2) - - (2,1) - - 2(2,-3)+(3,4) - 3$P - $P+2$m - - - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’3,2)"); - cy.get(cesc2("#/P1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,βˆ’2)"); - cy.get(cesc2("#/P2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,3)"); - cy.get(cesc2("#/P3") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’4,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/polygon"].stateValues.vertices).eqls([ - [7, -2], - [6, 3], - [-4, 5], - ]); - }); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/polygon", - args: { - pointCoords: { 0: [3, 5] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(6,3)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’4,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/polygon"].stateValues.vertices).eqls([ - [3, 5], - [6, 3], - [-4, 5], - ]); - }); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/polygon", - args: { - pointCoords: { 1: [-9, -6] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(βˆ’9,βˆ’6)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’9,2)"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/polygon", - args: { - pointCoords: { 2: [-3, 1] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(9,βˆ’9)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’3,1)"); - }); - - it("changing styles", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - - - - - - - - - - -

First polygon is $p1.styleDescription{assignNames="st1"}. It is a $p1.styleDescriptionWithNoun{assignNames="stn1"}. - Its border is $p1.borderStyleDescription{assignNames="bst1"}. Its fill is $p1.fillStyleDescription{assignNames="fst1"}. -

-

Second polygon is $p2.styleDescription{assignNames="st2"}. It is a $p2.styleDescriptionWithNoun{assignNames="stn2"}. - Its border is $p2.borderStyleDescription{assignNames="bst2"}. Its fill is $p2.fillStyleDescription{assignNames="fst2"}. -

-

Third polygon is $p3.styleDescription{assignNames="st3"}. It is a $p3.styleDescriptionWithNoun{assignNames="stn3"}. - Its border is $p3.borderStyleDescription{assignNames="bst3"}. Its fill is $p3.fillStyleDescription{assignNames="fst3"}. -

-

Fourth polygon is $p4.styleDescription{assignNames="st4"}. It is a $p4.styleDescriptionWithNoun{assignNames="stn4"}. - Its border is $p4.borderStyleDescription{assignNames="bst4"}. Its fill is $p4.fillStyleDescription{assignNames="fst4"}. -

- -

Fifth polygon is $p5.styleDescription{assignNames="st5"}. It is a $p5.styleDescriptionWithNoun{assignNames="stn5"}. - Its border is $p5.borderStyleDescription{assignNames="bst5"}. Its fill is $p5.fillStyleDescription{assignNames="fst5"}. -

-

Sixth polygon is $p6.styleDescription{assignNames="st6"}. It is a $p6.styleDescriptionWithNoun{assignNames="stn6"}. - Its border is $p6.borderStyleDescription{assignNames="bst6"}. Its fill is $p6.fillStyleDescription{assignNames="fst6"}. -

-

Seventh polygon is $p7.styleDescription{assignNames="st7"}. It is a $p7.styleDescriptionWithNoun{assignNames="stn7"}. - Its border is $p7.borderStyleDescription{assignNames="bst7"}. Its fill is $p7.fillStyleDescription{assignNames="fst7"}. -

-

Eighth polygon is $p8.styleDescription{assignNames="st8"}. It is a $p8.styleDescriptionWithNoun{assignNames="stn8"}. - Its border is $p8.borderStyleDescription{assignNames="bst8"}. Its fill is $p8.fillStyleDescription{assignNames="fst8"}. -

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/st1")).should("have.text", "blue"); - cy.get(cesc("#\\/stn1")).should("have.text", "blue polygon"); - cy.get(cesc("#\\/bst1")).should("have.text", "blue"); - cy.get(cesc("#\\/fst1")).should("have.text", "unfilled"); - - cy.get(cesc("#\\/st2")).should("have.text", "filled blue"); - cy.get(cesc("#\\/stn2")).should("have.text", "filled blue polygon"); - cy.get(cesc("#\\/bst2")).should("have.text", "blue"); - cy.get(cesc("#\\/fst2")).should("have.text", "blue"); - - cy.get(cesc("#\\/st3")).should("have.text", "red"); - cy.get(cesc("#\\/stn3")).should("have.text", "red polygon"); - cy.get(cesc("#\\/bst3")).should("have.text", "red"); - cy.get(cesc("#\\/fst3")).should("have.text", "unfilled"); - - cy.get(cesc("#\\/st4")).should( - "have.text", - "filled green with red border", - ); - cy.get(cesc("#\\/stn4")).should( - "have.text", - "filled green polygon with a red border", - ); - cy.get(cesc("#\\/bst4")).should("have.text", "red"); - cy.get(cesc("#\\/fst4")).should("have.text", "green"); - - cy.get(cesc("#\\/st5")).should("have.text", "thick blue"); - cy.get(cesc("#\\/stn5")).should("have.text", "thick blue polygon"); - cy.get(cesc("#\\/bst5")).should("have.text", "thick blue"); - cy.get(cesc("#\\/fst5")).should("have.text", "unfilled"); - - cy.get(cesc("#\\/st6")).should( - "have.text", - "filled blue with thick border", - ); - cy.get(cesc("#\\/stn6")).should( - "have.text", - "filled blue polygon with a thick border", - ); - cy.get(cesc("#\\/bst6")).should("have.text", "thick blue"); - cy.get(cesc("#\\/fst6")).should("have.text", "blue"); - - cy.get(cesc("#\\/st7")).should("have.text", "thin dotted red"); - cy.get(cesc("#\\/stn7")).should("have.text", "thin dotted red polygon"); - cy.get(cesc("#\\/bst7")).should("have.text", "thin dotted red"); - cy.get(cesc("#\\/fst7")).should("have.text", "unfilled"); - - cy.get(cesc("#\\/st8")).should( - "have.text", - "filled green with thin dotted red border", - ); - cy.get(cesc("#\\/stn8")).should( - "have.text", - "filled green polygon with a thin dotted red border", - ); - cy.get(cesc("#\\/bst8")).should("have.text", "thin dotted red"); - cy.get(cesc("#\\/fst8")).should("have.text", "green"); - }); - - it("draggable, vertices draggable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - -

To wait:

-

draggable:

-

vertices draggable:

-

all vertices: $p.vertices

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([1, 3]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - - cy.log("cannot move single vertex"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: { 0: [4, 7] }, - }, - }); - }); - - // wait for core to process click - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/bi2")).should("have.text", "true"); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([1, 3]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - - cy.log("cannot move all vertices"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: [ - [4, 7], - [8, 10], - [1, 9], - ], - }, - }); - }); - - // wait for core to process click - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/bi2")).should("have.text", "false"); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([1, 3]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - - cy.log("only vertices draggable"); - - cy.get(cesc("#\\/verticesDraggable")).click(); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.log("can move single vertex"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: { 0: [4, 7] }, - }, - }); - }); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow").should( - "contain.text", - "(4,7)", - ); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([4, 7]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); - }); - - cy.log("cannot move all vertices"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: [ - [3, 8], - [8, 10], - [1, 9], - ], - }, - }); - }); - - // wait for core to process click - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/bi2")).should("have.text", "true"); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([4, 7]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); - }); - - cy.log("vertices and polygon draggable"); - - cy.get(cesc("#\\/draggable")).click(); - cy.get(cesc("#\\/d2")).should("have.text", "true"); - - cy.log("can move single vertex"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: { 1: [-3, 2] }, - }, - }); - }); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow").should( - "contain.text", - "(βˆ’3,2)", - ); - - cy.get(cesc("#\\/d2")).should("have.text", "true"); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(βˆ’3,2)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([4, 7]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([-3, 2]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(true); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); - }); - - cy.log("can move all vertices"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: [ - [3, 8], - [8, 10], - [1, 9], - ], - }, - }); - }); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow").should( - "contain.text", - "(3,8)", - ); - - cy.get(cesc("#\\/d2")).should("have.text", "true"); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,8)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(8,10)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(1,9)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([3, 8]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([8, 10]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([1, 9]); - expect(stateVariables["/p"].stateValues.draggable).eq(true); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); - }); - - cy.log("polygon but not vertices draggable"); - - cy.get(cesc("#\\/verticesDraggable")).click(); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.log("cannot move single vertex"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: { 2: [9, 3] }, - }, - }); - }); - - // wait for core to process click - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/bi2")).should("have.text", "false"); - - cy.get(cesc("#\\/d2")).should("have.text", "true"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,8)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(8,10)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(1,9)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([3, 8]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([8, 10]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([1, 9]); - expect(stateVariables["/p"].stateValues.draggable).eq(true); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - - cy.log("can move all vertices"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: [ - [-4, 1], - [9, -4], - [0, 7], - ], - }, - }); - }); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow").should( - "contain.text", - "(βˆ’4,1)", - ); - - cy.get(cesc("#\\/d2")).should("have.text", "true"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’4,1)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(9,βˆ’4)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(0,7)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([-4, 1]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([9, -4]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([0, 7]); - expect(stateVariables["/p"].stateValues.draggable).eq(true); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - }); - - it("style description changes with theme", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - - - - - - -

Polygon A is $A.styleDescription.

-

B is a $B.styleDescriptionWithNoun.

-

C is a $C.styleDescriptionWithNoun.

-

A has a $A.borderStyleDescription border.

-

B has a $B.borderStyleDescription border.

-

C has a $C.borderStyleDescription border.

-

A has a $A.fillStyleDescription fill.

-

B has a $B.fillStyleDescription fill.

-

C has a $C.fillStyleDescription fill.

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/Adescrip")).should( - "have.text", - "Polygon A is filled brown with thick border.", - ); - cy.get(cesc("#\\/Bdescrip")).should( - "have.text", - "B is a filled dark red polygon.", - ); - cy.get(cesc("#\\/Cdescrip")).should( - "have.text", - "C is a filled black polygon with a thin border.", - ); - cy.get(cesc("#\\/Aborderdescrip")).should( - "have.text", - "A has a thick brown border.", - ); - cy.get(cesc("#\\/Bborderdescrip")).should( - "have.text", - "B has a dark red border.", - ); - cy.get(cesc("#\\/Cborderdescrip")).should( - "have.text", - "C has a thin black border.", - ); - cy.get(cesc("#\\/Afilldescrip")).should( - "have.text", - "A has a brown fill.", - ); - cy.get(cesc("#\\/Bfilldescrip")).should( - "have.text", - "B has a dark red fill.", - ); - cy.get(cesc("#\\/Cfilldescrip")).should( - "have.text", - "C has a black fill.", - ); - - cy.log("set dark mode"); - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_darkMode").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - cy.get(cesc("#\\/Adescrip")).should( - "have.text", - "Polygon A is filled yellow with thick border.", - ); - cy.get(cesc("#\\/Bdescrip")).should( - "have.text", - "B is a filled light red polygon.", - ); - cy.get(cesc("#\\/Cdescrip")).should( - "have.text", - "C is a filled white polygon with a thin border.", - ); - cy.get(cesc("#\\/Aborderdescrip")).should( - "have.text", - "A has a thick yellow border.", - ); - cy.get(cesc("#\\/Bborderdescrip")).should( - "have.text", - "B has a light red border.", - ); - cy.get(cesc("#\\/Cborderdescrip")).should( - "have.text", - "C has a thin white border.", - ); - cy.get(cesc("#\\/Afilldescrip")).should( - "have.text", - "A has a yellow fill.", - ); - cy.get(cesc("#\\/Bfilldescrip")).should( - "have.text", - "B has a light red fill.", - ); - cy.get(cesc("#\\/Cfilldescrip")).should( - "have.text", - "C has a white fill.", - ); - }); - - it("One vertex constrained to grid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,5) - (-4,-1) - (5,2) - - - - - (-3,4) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 5], - [-4, -1], - [6, 4], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right"); - cy.window().then(async (win) => { - let moveX = 4; - let moveY = 3; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = 1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("try to move double copied polygon down and to the right"); - cy.window().then(async (win) => { - let moveX = 1; - let moveY = -7; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = -1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Two vertices constrained to same grid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,5) - - - - - (-4,-1) - (5,2) - - - - - (-3,4) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 4], - [-4, -1], - [6, 4], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right"); - cy.window().then(async (win) => { - let moveX = 4; - let moveY = 3; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = 1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("try to move double copied polygon down and to the right"); - cy.window().then(async (win) => { - let moveX = 1; - let moveY = -7; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = -1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Three vertices constrained to same grid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,5) - - - - - (-4,-1) - - - - - (5,2) - - - - - (-3,4) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 4], - [-3, 0], - [6, 4], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); - - // adjust for constraint - vertices[1] = [3, 8]; - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right"); - cy.window().then(async (win) => { - let moveX = 4; - let moveY = 3; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = 1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("try to move double copied polygon down and to the right"); - cy.window().then(async (win) => { - let moveX = 1; - let moveY = -7; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = -1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Two vertices fixed, handle rounding error from third calculated vertex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - (-1,-1) - (5,2) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3"}) - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [1, 2], - [-3, -3], - [5, 2], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log( - "try to move polygon where calculated vertex can't be represented exactly", - ); - cy.window().then(async (win) => { - // key point: (desiredVertex2X/3)*3 !== desiredVertex2X due to round off error - let desiredVertex2X = 0.38823529411764707; - let desiredVertex2Y = -2.7803926355698527; - - let moveX = desiredVertex2X - vertices[1][0]; - let moveY = desiredVertex2Y - vertices[1][1]; - - let desiredVertices = []; - - for (let i = 0; i < vertices.length; i++) { - if (i === 1) { - desiredVertices.push([desiredVertex2X, desiredVertex2Y]); - } else { - desiredVertices.push([ - vertices[i][0] + moveX, - vertices[i][1] + moveY, - ]); - } - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: desiredVertices, - }, - }); - - // since nothing is supposed to happen, click boolean to wait for core - cy.get(cesc2("#/bi")).click(); - cy.get(cesc2("#/bi2")).should("have.text", "true"); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("handle bad vertices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // page loads - cy.get(cesc2("#/_text1")).should("have.text", "a"); - }); - - it("area and perimeter", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - -

Area:

-

Perimeter:

- `, - }, - "*", - ); - }); - - let area = 5 * 2 + 1 + (8 * 5) / 2; - let perimeter = 5 + 2 * Math.sqrt(2) + Math.sqrt(25 + 64) + 10; - - cy.get(cesc2("#/area")).should("have.text", `${area}`); - cy.get(cesc2("#/perimeter")).should( - "have.text", - `${Math.round(perimeter * 100) / 100}`, - ); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: { 1: [-8, -4] }, - }, - }); - win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: { 2: [-8, 2] }, - }, - }); - - area = 2 * 8 + (4 * 8) / 2 - (5 * 8) / 2; - perimeter = 13 + 6 + Math.sqrt(16 + 64) + 10 + Math.sqrt(25 + 64); - - cy.get(cesc2("#/area")).should("have.text", `${area}`); - cy.get(cesc2("#/perimeter")).should( - "have.text", - `${Math.round(perimeter * 100) / 100}`, - ); - }); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: { 3: [8, 2] }, - }, - }); - - perimeter = 16 + 6 + Math.sqrt(16 + 64) + 10 + Math.sqrt(64 + 64); - - cy.get(cesc2("#/area")).should("have.text", `0`); - cy.get(cesc2("#/perimeter")).should( - "have.text", - `${Math.round(perimeter * 100) / 100}`, - ); - }); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolygon", - componentName: "/p", - args: { - pointCoords: { 0: [0, 2] }, - }, - }); - - area = (8 * 8) / 2 - (8 * 6) / 2; - - perimeter = 16 + 6 + Math.sqrt(36 + 64) + 8 + Math.sqrt(64 + 64); - - cy.get(cesc2("#/area")).should("have.text", `${area}`); - cy.get(cesc2("#/perimeter")).should( - "have.text", - `${Math.round(perimeter * 100) / 100}`, - ); - }); - }); - - it("Rigid polygon", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex rotates"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 90 degrees counterclockwise around centroid - // (shrinking by 1/2, but that will be ignored) - let requested_vertex_1 = [ - -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - -(v[1] - centroid[1]) + centroid[0], - v[0] - centroid[0] + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right chooses minimum moved"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move double copied individual vertex, getting rotation"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 180 degrees around centroid - // (doubling length, but that will be ignored) - let requested_vertex_2 = [ - -2 * (vertices[2][0] - centroid[0]) + centroid[0], - -2 * (vertices[2][1] - centroid[1]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - -(v[0] - centroid[0]) + centroid[0], - -(v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving single copied vertex gets rotation"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 90 degrees clockwise around centroid - // (shrinking by 1/4, but that will be ignored) - let requested_vertex_3 = [ - 0.25 * (vertices[3][1] - centroid[1]) + centroid[0], - -0.25 * (vertices[3][0] - centroid[0]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - v[1] - centroid[1] + centroid[0], - -(v[0] - centroid[0]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; - - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - // it("Rigid polygon, vertex constraint", () => { - // cy.window().then(async (win) => { - // win.postMessage( - // { - // doenetML: ` - // a - // - // (3,7) - // (-4,-1) - // (8,2) - // (-3,4) - - // (1,9) - // - // - // $a1 - // - // - // - // - // $(../g1/pg{name="pg"}) - // - // $g2{name="g3"} - // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - // `, - // }, - // "*", - // ); - // }); - // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // let vertices = [ - // [3, 7], - // [-4, -1], - // [8, 2], - // [-3, 4], - // ]; - - // let centroid = vertices.reduce( - // (a, c) => [a[0] + c[0], a[1] + c[1]], - // [0, 0], - // ); - // centroid[0] /= 4; - // centroid[1] /= 4; - - // testPolygonCopiedTwice({ vertices }); - - // cy.log("move individual vertex rotates, attracts to point"); - // cy.window().then(async (win) => { - // // rotate by 90 degrees counterclockwise around centroid - // // (shrinking by 1/2, but that will be ignored) - // let requested_vertex_1 = [ - // -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - // 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - // ]; - // vertices = vertices.map((v) => [ - // -(v[1] - centroid[1]) + centroid[0], - // v[0] - centroid[0] + centroid[1], - // ]); - // // since attracted to point, moves down one and to the left - // vertices = vertices.map((v) => [v[0] - 1, v[1] - 1]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g1/pg", - // args: { - // pointCoords: { 1: requested_vertex_1 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log("rotating further so no attraction preserves old centroid"); - // cy.window().then(async (win) => { - // // location of vertices if weren't attracted to point, moves up one and to the right - // vertices = vertices.map((v) => [v[0] + 1, v[1] + 1]); - - // // rotate by another 90 degrees counterclockwise around centroid - // // (doubling but that will be ignored) - // let requested_vertex_1 = [ - // -2 * (vertices[1][1] - centroid[1]) + centroid[0], - // 2 * (vertices[1][0] - centroid[0]) + centroid[1], - // ]; - // vertices = vertices.map((v) => [ - // -(v[1] - centroid[1]) + centroid[0], - // v[0] - centroid[0] + centroid[1], - // ]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g1/pg", - // args: { - // pointCoords: { 1: requested_vertex_1 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log( - // "move copied polygon up and to the left chooses minimum moved and gets attracted", - // ); - // cy.window().then(async (win) => { - // let moveX = -4; - // let moveY = 1; - - // // add extra movement to requested vertices, which will be ignored - // let requested_vertices = []; - // for (let i = 0; i < vertices.length; i++) { - // vertices[i][0] = vertices[i][0] + moveX; - // vertices[i][1] = vertices[i][1] + moveY; - // requested_vertices.push([ - // vertices[i][0] - i, - // vertices[i][1] + 2 * i, - // ]); - // } - - // // since attracted to point, moves up one and to the left - // vertices = vertices.map((v) => [v[0] - 1, v[1] + 1]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g2/pg", - // args: { - // pointCoords: requested_vertices, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log( - // "move double copied individual vertex, getting rotation around new centroid", - // ); - // cy.window().then(async (win) => { - // let centroid = vertices.reduce( - // (a, c) => [a[0] + c[0], a[1] + c[1]], - // [0, 0], - // ); - // centroid[0] /= 4; - // centroid[1] /= 4; - - // // rotate by 180 degrees around centroid - // // (doubling length, but that will be ignored) - // let requested_vertex_2 = [ - // -2 * (vertices[2][0] - centroid[0]) + centroid[0], - // -2 * (vertices[2][1] - centroid[1]) + centroid[1], - // ]; - // vertices = vertices.map((v) => [ - // -(v[0] - centroid[0]) + centroid[0], - // -(v[1] - centroid[1]) + centroid[1], - // ]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g3/pg", - // args: { - // pointCoords: { 2: requested_vertex_2 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - // }); - - // it("Rigid polygon, three vertex constraints", () => { - // cy.window().then(async (win) => { - // win.postMessage( - // { - // doenetML: ` - // a - // - // (3,7) - // (-4,-1) - // (8,2) - // (-3,4) - - // (1,9) - // (5,-1) - // (-9,5) - // - // - // $a1$a2$a3 - // - // - // - // - // $(../g1/pg{name="pg"}) - // - // $g2{name="g3"} - // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - // `, - // }, - // "*", - // ); - // }); - // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // let vertices = [ - // [3, 7], - // [-4, -1], - // [8, 2], - // [-3, 4], - // ]; - - // let centroid = vertices.reduce( - // (a, c) => [a[0] + c[0], a[1] + c[1]], - // [0, 0], - // ); - // centroid[0] /= 4; - // centroid[1] /= 4; - - // testPolygonCopiedTwice({ vertices }); - - // cy.log("move individual vertex rotates, attracts to closest point"); - // cy.window().then(async (win) => { - // // rotate by 90 degrees counterclockwise around centroid - // // (shrinking by 1/2, but that will be ignored) - // let requested_vertex_1 = [ - // -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - // 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - // ]; - // vertices = vertices.map((v) => [ - // -(v[1] - centroid[1]) + centroid[0], - // v[0] - centroid[0] + centroid[1], - // ]); - // // since attracted to closest point (5,-2), moves up one - // vertices = vertices.map((v) => [v[0], v[1] + 1]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g1/pg", - // args: { - // pointCoords: { 1: requested_vertex_1 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log("rotating further so no attraction preserves old centroid"); - // cy.window().then(async (win) => { - // // location of vertices if weren't attracted to point, moves down one - // vertices = vertices.map((v) => [v[0], v[1] - 1]); - - // // rotate by another 90 degrees counterclockwise around centroid - // // (doubling but that will be ignored) - // let requested_vertex_1 = [ - // -2 * (vertices[1][1] - centroid[1]) + centroid[0], - // 2 * (vertices[1][0] - centroid[0]) + centroid[1], - // ]; - // vertices = vertices.map((v) => [ - // -(v[1] - centroid[1]) + centroid[0], - // v[0] - centroid[0] + centroid[1], - // ]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g1/pg", - // args: { - // pointCoords: { 1: requested_vertex_1 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log( - // "move copied polygon up and to the left chooses minimum moved and gets attracted", - // ); - // cy.window().then(async (win) => { - // let moveX = -4; - // let moveY = 1; - - // // add extra movement to requested vertices, which will be ignored - // let requested_vertices = []; - // for (let i = 0; i < vertices.length; i++) { - // vertices[i][0] = vertices[i][0] + moveX; - // vertices[i][1] = vertices[i][1] + moveY; - // requested_vertices.push([ - // vertices[i][0] - i, - // vertices[i][1] + 2 * i, - // ]); - // } - - // // since attracted to point (-9,5), moves one to the right - // vertices = vertices.map((v) => [v[0] + 1, v[1]]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g2/pg", - // args: { - // pointCoords: requested_vertices, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log( - // "move double copied individual vertex, getting rotation around new centroid, then attracted to point", - // ); - // cy.window().then(async (win) => { - // let centroid = vertices.reduce( - // (a, c) => [a[0] + c[0], a[1] + c[1]], - // [0, 0], - // ); - // centroid[0] /= 4; - // centroid[1] /= 4; - - // // rotate by 180 degrees around centroid - // // (doubling length, but that will be ignored) - // let requested_vertex_2 = [ - // -2 * (vertices[2][0] - centroid[0]) + centroid[0], - // -2 * (vertices[2][1] - centroid[1]) + centroid[1], - // ]; - // vertices = vertices.map((v) => [ - // -(v[0] - centroid[0]) + centroid[0], - // -(v[1] - centroid[1]) + centroid[1], - // ]); - - // // since a different vertex is attracted to point (1,9), moves one up and to the right - // vertices = vertices.map((v) => [v[0] + 1, v[1] + 1]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g3/pg", - // args: { - // pointCoords: { 2: requested_vertex_2 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - // }); - - // it("Non-rigid polygon, three vertex constraints", () => { - // cy.window().then(async (win) => { - // win.postMessage( - // { - // doenetML: ` - // a - // - // (3,7) - // (-4,-1) - // (8,2) - // (-3,4) - - // (1,9) - // (5,-1) - // (-9,5) - // - // - // $a1$a2$a3 - // - // - // - // - // $(../g1/pg{name="pg"}) - // $pg.vertices{assignNames="v1 v2 v3 v4"} - // - // $g2{name="g3"} - // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - // `, - // }, - // "*", - // ); - // }); - // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // let vertices = [ - // [3, 7], - // [-4, -1], - // [8, 2], - // [-3, 4], - // ]; - - // testPolygonCopiedTwice({ vertices }); - - // cy.log("move individual vertex, attracts to closest point"); - // cy.window().then(async (win) => { - // let requested_vertex_1 = [-10, 6]; - - // vertices[1] = [-9, 5]; - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g1/pg", - // args: { - // pointCoords: { 1: requested_vertex_1 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log("Moving entire polygon up attract to another point"); - - // cy.window().then(async (win) => { - // let moveX = -1; - // let moveY = 1; - - // let requested_vertices = []; - // for (let i = 0; i < vertices.length; i++) { - // vertices[i][0] = vertices[i][0] + moveX; - // vertices[i][1] = vertices[i][1] + moveY; - // requested_vertices.push([vertices[i][0], vertices[i][1]]); - // } - - // // since attracted to point (1,9), moves one up and to the left - // vertices = vertices.map((v) => [v[0] - 1, v[1] + 1]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g2/pg", - // args: { - // pointCoords: requested_vertices, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log("move double copied individual vertex"); - // cy.window().then(async (win) => { - // vertices[2] = [2, 1]; - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g3/pg", - // args: { - // pointCoords: { 2: vertices[2] }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log("Moving entire polygon near two points, attracts to just one"); - // cy.window().then(async (win) => { - // let moveX = 2.6; - // let moveY = -2; - - // let requested_vertices = []; - // for (let i = 0; i < vertices.length; i++) { - // vertices[i][0] = vertices[i][0] + moveX; - // vertices[i][1] = vertices[i][1] + moveY; - // requested_vertices.push([vertices[i][0], vertices[i][1]]); - // } - - // // since attracted to point (5,-1), moves 0.4 to the right - // vertices = vertices.map((v) => [v[0] + 0.4, v[1]]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g2/pg", - // args: { - // pointCoords: requested_vertices, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log( - // "Moving just one vertex attracts to other nearby vertex to attractor", - // ); - // cy.window().then(async (win) => { - // let requested_vertex_0 = [0, 10]; - // vertices[0] = [1, 9]; - // vertices[1] = [-9, 5]; - - // win.callAction1({ - // actionName: "movePoint", - // componentName: "/g2/v1", - // args: { x: requested_vertex_0[0], y: requested_vertex_0[1] }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - // }); - - // it("Rigid polygon, vertices attracted to polygon", () => { - // cy.window().then(async (win) => { - // win.postMessage( - // { - // doenetML: ` - // a - // - // - - // (-1,0) - // (3,0) - // (1,-3) - // - // - // $pa - // - // - // - // - // $(../g1/pg{name="pg"}) - // - // $g2{name="g3"} - // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - // `, - // }, - // "*", - // ); - // }); - // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // cy.log("start shifted so that two vertices are attracted"); - - // let vertices = [ - // [0, 0], - // [4, 0], - // [2, -3], - // ]; - - // testPolygonCopiedTwice({ vertices }); - - // cy.log("move individual vertex rotates, attracts to edge of polygon"); - - // let centroid = vertices.reduce( - // (a, c) => [a[0] + c[0], a[1] + c[1]], - // [0, 0], - // ); - // centroid[0] /= 3; - // centroid[1] /= 3; - - // cy.window().then(async (win) => { - // // shift 1 to left to give original before attraction - // centroid[0] -= 1; - // vertices = vertices.map((v) => [v[0] - 1, v[1]]); - - // // rotate by 90 degrees clockwise around centroid - // // (shrinking by 1/2, but that will be ignored) - // let requested_vertex_1 = [ - // 0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - // -0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - // ]; - // vertices = vertices.map((v) => [ - // v[1] - centroid[1] + centroid[0], - // -(v[0] - centroid[0]) + centroid[1], - // ]); - // // since attracted to edge, moves down one and to the left - // vertices = vertices.map((v) => [v[0], v[1] - 1]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g1/pg", - // args: { - // pointCoords: { 1: requested_vertex_1 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log("move copied polygon up and to the right"); - // cy.window().then(async (win) => { - // // Move so that bottom right gets attracted to (4,6). - // // Slope of orthogonal to attractor edge is -6/9. - // // So move bottom right to (4,6) + (9,-6)/10 - - // let requested_bottom_right = [4 + 0.9, 6 - 0.6]; - // let actual_bottom_right = [4, 6]; - - // let moveX = requested_bottom_right[0] - vertices[1][0]; - // let moveY = requested_bottom_right[1] - vertices[1][1]; - - // // add extra movement to requested vertices, which will be ignored - // let requested_vertices = []; - // for (let i = 0; i < vertices.length; i++) { - // vertices[i][0] = vertices[i][0] + moveX; - // vertices[i][1] = vertices[i][1] + moveY; - // requested_vertices.push([ - // vertices[i][0] + i, - // vertices[i][1] + 2 * i, - // ]); - // } - - // // since attracted to point, moves up one and to the left - // vertices = vertices.map((v) => [ - // v[0] + actual_bottom_right[0] - requested_bottom_right[0], - // v[1] + actual_bottom_right[1] - requested_bottom_right[1], - // ]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g2/pg", - // args: { - // pointCoords: requested_vertices, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - // }); - - // it("Rigid polygon, vertices attracted to polyline", () => { - // cy.window().then(async (win) => { - // win.postMessage( - // { - // doenetML: ` - // a - // - // - - // (-1,0) - // (3,0) - // (1,-3) - // - // - // $pa - // - // - // - // - // $(../g1/pg{name="pg"}) - // - // $g2{name="g3"} - // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - // `, - // }, - // "*", - // ); - // }); - // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // cy.log("start shifted so that two vertices are attracted"); - - // let vertices = [ - // [0, 0], - // [4, 0], - // [2, -3], - // ]; - - // testPolygonCopiedTwice({ vertices }); - - // cy.log("move individual vertex rotates, attracts to edge of polygon"); - - // let centroid = vertices.reduce( - // (a, c) => [a[0] + c[0], a[1] + c[1]], - // [0, 0], - // ); - // centroid[0] /= 3; - // centroid[1] /= 3; - - // cy.window().then(async (win) => { - // // shift 1 to left to give original before attraction - // centroid[0] -= 1; - // vertices = vertices.map((v) => [v[0] - 1, v[1]]); - - // // rotate by 90 degrees clockwise around centroid - // // (shrinking by 1/2, but that will be ignored) - // let requested_vertex_1 = [ - // 0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - // -0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - // ]; - // vertices = vertices.map((v) => [ - // v[1] - centroid[1] + centroid[0], - // -(v[0] - centroid[0]) + centroid[1], - // ]); - // // since attracted to edge, moves down one and to the left - // vertices = vertices.map((v) => [v[0], v[1] - 1]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g1/pg", - // args: { - // pointCoords: { 1: requested_vertex_1 }, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - - // cy.log("move copied polygon up and to the right"); - // cy.window().then(async (win) => { - // // Move so that bottom right would get attracted to (4,6) if it where a polygon. - // // But since it is a polyline, that edge doesn't exist - // // and instead the upper right gets attracted to other edge. - - // // If had polygon, - // // slope of orthogonal to attractor edge would be -6/9. - // // So move bottom right to (4,6) + (9,-6)/10 - - // let requested_bottom_right = [4 + 0.9, 6 - 0.6]; - // let actual_bottom_right = [6, 5]; - - // let moveX = requested_bottom_right[0] - vertices[1][0]; - // let moveY = requested_bottom_right[1] - vertices[1][1]; - - // // add extra movement to requested vertices, which will be ignored - // let requested_vertices = []; - // for (let i = 0; i < vertices.length; i++) { - // vertices[i][0] = vertices[i][0] + moveX; - // vertices[i][1] = vertices[i][1] + moveY; - // requested_vertices.push([ - // vertices[i][0] + i, - // vertices[i][1] + 2 * i, - // ]); - // } - - // // since attracted to point, moves up one and to the left - // vertices = vertices.map((v) => [ - // v[0] + actual_bottom_right[0] - requested_bottom_right[0], - // v[1] + actual_bottom_right[1] - requested_bottom_right[1], - // ]); - - // win.callAction1({ - // actionName: "movePolygon", - // componentName: "/g2/pg", - // args: { - // pointCoords: requested_vertices, - // }, - // }); - - // testPolygonCopiedTwice({ vertices }); - // }); - // }); - - it("Preserve similarity", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex rotates and dilates"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 90 degrees counterclockwise around centroid - // and shrinking by 1/2 - let requested_vertex_1 = [ - -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - -0.5 * (v[1] - centroid[1]) + centroid[0], - 0.5 * (v[0] - centroid[0]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right chooses minimum moved"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log( - "move double copied individual vertex, getting rotation and dilation", - ); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 180 degrees around centroid - // and doubling length - let requested_vertex_2 = [ - -2 * (vertices[2][0] - centroid[0]) + centroid[0], - -2 * (vertices[2][1] - centroid[1]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - -2 * (v[0] - centroid[0]) + centroid[0], - -2 * (v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving single copied vertex gets rotation and dilation"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 90 degrees clockwise around centroid - // and shrinking by 1/4 - let requested_vertex_3 = [ - 0.25 * (vertices[3][1] - centroid[1]) + centroid[0], - -0.25 * (vertices[3][0] - centroid[0]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - 0.25 * (v[1] - centroid[1]) + centroid[0], - -0.25 * (v[0] - centroid[0]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; - - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Preserve similarity and don't allow dilation equals rigid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex rotates"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 90 degrees counterclockwise around centroid - // (shrinking by 1/2, but that will be ignored) - let requested_vertex_1 = [ - -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - -(v[1] - centroid[1]) + centroid[0], - v[0] - centroid[0] + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right chooses minimum moved"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Rigid supersedes setting preserveSimilarity to false or allowDilation to true", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex rotates"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 90 degrees counterclockwise around centroid - // (shrinking by 1/2, but that will be ignored) - let requested_vertex_1 = [ - -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - -(v[1] - centroid[1]) + centroid[0], - v[0] - centroid[0] + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right chooses minimum moved"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Don't allow rotation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4" displayDigits="6"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex only dilates"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // shrink to half size by moving vertex so projects to half - // on the segment from centroid to original vertex - let midpoint = [ - (centroid[0] + vertices[1][0]) / 2, - (centroid[1] + vertices[1][1]) / 2, - ]; - let vector_to_v1 = [ - vertices[1][0] - centroid[0], - vertices[1][1] - centroid[1], - ]; - let rotate_vector = [-3 * vector_to_v1[1], 3 * vector_to_v1[0]]; - - let requested_vertex_1 = [ - midpoint[0] + rotate_vector[0], - midpoint[1] + rotate_vector[1], - ]; - vertices = vertices.map((v) => [ - 0.5 * (v[0] - centroid[0]) + centroid[0], - 0.5 * (v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right chooses minimum moved"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log( - "move double copied individual vertex, attempting to rotation 90 degrees shrinks to minimum", - ); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // attempt to rotate by 90 degrees around centroid - let requested_vertex_2 = [ - 2 * (vertices[2][1] - centroid[1]) + centroid[0], - -2 * (vertices[2][0] - centroid[0]) + centroid[1], - ]; - - // distance from vertex 2 and centroid becomes minShrink = 0.1 - let shrink_factor = - 0.1 / - Math.sqrt( - (vertices[2][1] - centroid[1]) ** 2 + - (vertices[2][0] - centroid[0]) ** 2, - ); - - vertices = vertices.map((v) => [ - shrink_factor * (v[0] - centroid[0]) + centroid[0], - shrink_factor * (v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving single copied vertex to dilate"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // Make 10 times larger by moving vertex so projects to 10 times the length on - // on the segment from centroid to original vertex - let extended_point = [ - 10 * vertices[3][0] - 9 * centroid[0], - 10 * vertices[3][1] - 9 * centroid[1], - ]; - let vector_to_v3 = [ - vertices[3][0] - centroid[0], - vertices[3][1] - centroid[1], - ]; - let rotate_vector = [0.5 * vector_to_v3[1], -0.5 * vector_to_v3[0]]; - - let requested_vertex_3 = [ - extended_point[0] + rotate_vector[0], - extended_point[1] + rotate_vector[1], - ]; - vertices = vertices.map((v) => [ - 10 * (v[0] - centroid[0]) + centroid[0], - 10 * (v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; - - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Don't allow rotation, large minShrink", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4" displayDigits="8"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex only dilates"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // shrink to half size by moving vertex so projects to half - // on the segment from centroid to original vertex - let midpoint = [ - (centroid[0] + vertices[1][0]) / 2, - (centroid[1] + vertices[1][1]) / 2, - ]; - let vector_to_v1 = [ - vertices[1][0] - centroid[0], - vertices[1][1] - centroid[1], - ]; - let rotate_vector = [-3 * vector_to_v1[1], 3 * vector_to_v1[0]]; - - let requested_vertex_1 = [ - midpoint[0] + rotate_vector[0], - midpoint[1] + rotate_vector[1], - ]; - vertices = vertices.map((v) => [ - 0.5 * (v[0] - centroid[0]) + centroid[0], - 0.5 * (v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up and to the right chooses minimum moved"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log( - "move double copied individual vertex, attempting to rotation 90 degrees shrinks to minimum", - ); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // attempt to rotate by 90 degrees around centroid - let requested_vertex_2 = [ - 2 * (vertices[2][1] - centroid[1]) + centroid[0], - -2 * (vertices[2][0] - centroid[0]) + centroid[1], - ]; - - // distance from vertex 2 and centroid becomes minShrink = 0.1 - let shrink_factor = - 2 / - Math.sqrt( - (vertices[2][1] - centroid[1]) ** 2 + - (vertices[2][0] - centroid[0]) ** 2, - ); - - vertices = vertices.map((v) => [ - shrink_factor * (v[0] - centroid[0]) + centroid[0], - shrink_factor * (v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving single copied vertex to dilate"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // Make 10 times larger by moving vertex so projects to 10 times the length on - // on the segment from centroid to original vertex - let extended_point = [ - 10 * vertices[3][0] - 9 * centroid[0], - 10 * vertices[3][1] - 9 * centroid[1], - ]; - let vector_to_v3 = [ - vertices[3][0] - centroid[0], - vertices[3][1] - centroid[1], - ]; - let rotate_vector = [0.5 * vector_to_v3[1], -0.5 * vector_to_v3[0]]; - - let requested_vertex_3 = [ - extended_point[0] + rotate_vector[0], - extended_point[1] + rotate_vector[1], - ]; - vertices = vertices.map((v) => [ - 10 * (v[0] - centroid[0]) + centroid[0], - 10 * (v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; - - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Don't allow translation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex rotates and dilates"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 90 degrees counterclockwise around centroid - // and shrinking by 1/2 - let requested_vertex_1 = [ - -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - -0.5 * (v[1] - centroid[1]) + centroid[0], - 0.5 * (v[0] - centroid[0]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("move copied polygon up does not move"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - // this translation will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - requested_vertices.push([ - vertices[i][0] + moveX, - vertices[i][1] + moveY, - ]); - } - - await win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log( - "move double copied individual vertex, getting rotation and dilation", - ); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 180 degrees around centroid - // and doubling length - let requested_vertex_2 = [ - -2 * (vertices[2][0] - centroid[0]) + centroid[0], - -2 * (vertices[2][1] - centroid[1]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - -2 * (v[0] - centroid[0]) + centroid[0], - -2 * (v[1] - centroid[1]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving single copied vertex gets rotation and dilation"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; - - // rotate by 90 degrees clockwise around centroid - // and shrinking by 1/4 - let requested_vertex_3 = [ - 0.25 * (vertices[3][1] - centroid[1]) + centroid[0], - -0.25 * (vertices[3][0] - centroid[0]) + centroid[1], - ]; - vertices = vertices.map((v) => [ - 0.25 * (v[1] - centroid[1]) + centroid[0], - -0.25 * (v[0] - centroid[0]) + centroid[1], - ]); - - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; - - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); - - testPolygonCopiedTwice({ vertices }); - }); - }); - - it("Only translation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; - - testPolygonCopiedTwice({ vertices }); - - cy.log("move individual vertex translates"); - cy.window().then(async (win) => { - let moveX = -1; - let moveY = -3; - let requested_vertex_1 = [ - vertices[1][0] + moveX, - vertices[1][1] + moveY, - ]; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } + // // rotate by 180 degrees around centroid + // // (doubling length, but that will be ignored) + // let requested_vertex_2 = [ + // -2 * (vertices[2][0] - centroid[0]) + centroid[0], + // -2 * (vertices[2][1] - centroid[1]) + centroid[1], + // ]; + // vertices = vertices.map((v) => [ + // -(v[0] - centroid[0]) + centroid[0], + // -(v[1] - centroid[1]) + centroid[1], + // ]); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g3/pg", + // args: { + // pointCoords: { 2: requested_vertex_2 }, + // }, + // }); - testPolygonCopiedTwice({ vertices }); - }); + // testPolygonCopiedTwice({ vertices }); + // }); + // }); - cy.log("move copied polygon up and to right"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; + // it("Rigid polygon, three vertex constraints", () => { + // cy.window().then(async (win) => { + // win.postMessage( + // { + // doenetML: ` + // a + // + // (3,7) + // (-4,-1) + // (8,2) + // (-3,4) - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } + // (1,9) + // (5,-1) + // (-9,5) + // + // + // $a1$a2$a3 + // + // + // + // + // $(../g1/pg{name="pg"}) + // + // $g2{name="g3"} + // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) + // `, + // }, + // "*", + // ); + // }); + // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - await win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); + // let vertices = [ + // [3, 7], + // [-4, -1], + // [8, 2], + // [-3, 4], + // ]; - testPolygonCopiedTwice({ vertices }); - }); + // let centroid = vertices.reduce( + // (a, c) => [a[0] + c[0], a[1] + c[1]], + // [0, 0], + // ); + // centroid[0] /= 4; + // centroid[1] /= 4; - cy.log("move double copied individual vertex, getting translation"); - cy.window().then(async (win) => { - let moveX = -8; - let moveY = 4; - let requested_vertex_2 = [ - vertices[2][0] + moveX, - vertices[2][1] + moveY, - ]; + // testPolygonCopiedTwice({ vertices }); - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } + // cy.log("move individual vertex rotates, attracts to closest point"); + // cy.window().then(async (win) => { + // // rotate by 90 degrees counterclockwise around centroid + // // (shrinking by 1/2, but that will be ignored) + // let requested_vertex_1 = [ + // -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + // 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + // ]; + // vertices = vertices.map((v) => [ + // -(v[1] - centroid[1]) + centroid[0], + // v[0] - centroid[0] + centroid[1], + // ]); + // // since attracted to closest point (5,-2), moves up one + // vertices = vertices.map((v) => [v[0], v[1] + 1]); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g1/pg", + // args: { + // pointCoords: { 1: requested_vertex_1 }, + // }, + // }); - testPolygonCopiedTwice({ vertices }); - }); + // testPolygonCopiedTwice({ vertices }); + // }); - cy.log("moving single copied vertex gets translation"); - cy.window().then(async (win) => { - let moveX = 2; - let moveY = -5; - let requested_vertex_3 = [ - vertices[3][0] + moveX, - vertices[3][1] + moveY, - ]; + // cy.log("rotating further so no attraction preserves old centroid"); + // cy.window().then(async (win) => { + // // location of vertices if weren't attracted to point, moves down one + // vertices = vertices.map((v) => [v[0], v[1] - 1]); - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } + // // rotate by another 90 degrees counterclockwise around centroid + // // (doubling but that will be ignored) + // let requested_vertex_1 = [ + // -2 * (vertices[1][1] - centroid[1]) + centroid[0], + // 2 * (vertices[1][0] - centroid[0]) + centroid[1], + // ]; + // vertices = vertices.map((v) => [ + // -(v[1] - centroid[1]) + centroid[0], + // v[0] - centroid[0] + centroid[1], + // ]); - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g1/pg", + // args: { + // pointCoords: { 1: requested_vertex_1 }, + // }, + // }); - testPolygonCopiedTwice({ vertices }); - }); + // testPolygonCopiedTwice({ vertices }); + // }); - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; + // cy.log( + // "move copied polygon up and to the left chooses minimum moved and gets attracted", + // ); + // cy.window().then(async (win) => { + // let moveX = -4; + // let moveY = 1; - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); + // // add extra movement to requested vertices, which will be ignored + // let requested_vertices = []; + // for (let i = 0; i < vertices.length; i++) { + // vertices[i][0] = vertices[i][0] + moveX; + // vertices[i][1] = vertices[i][1] + moveY; + // requested_vertices.push([ + // vertices[i][0] - i, + // vertices[i][1] + 2 * i, + // ]); + // } - testPolygonCopiedTwice({ vertices }); - }); - }); + // // since attracted to point (-9,5), moves one to the right + // vertices = vertices.map((v) => [v[0] + 1, v[1]]); - it("Don't allow any transformations", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g2/pg", + // args: { + // pointCoords: requested_vertices, + // }, + // }); - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; + // testPolygonCopiedTwice({ vertices }); + // }); - testPolygonCopiedTwice({ vertices }); + // cy.log( + // "move double copied individual vertex, getting rotation around new centroid, then attracted to point", + // ); + // cy.window().then(async (win) => { + // let centroid = vertices.reduce( + // (a, c) => [a[0] + c[0], a[1] + c[1]], + // [0, 0], + // ); + // centroid[0] /= 4; + // centroid[1] /= 4; - cy.log("move individual vertex doesn't move"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; + // // rotate by 180 degrees around centroid + // // (doubling length, but that will be ignored) + // let requested_vertex_2 = [ + // -2 * (vertices[2][0] - centroid[0]) + centroid[0], + // -2 * (vertices[2][1] - centroid[1]) + centroid[1], + // ]; + // vertices = vertices.map((v) => [ + // -(v[0] - centroid[0]) + centroid[0], + // -(v[1] - centroid[1]) + centroid[1], + // ]); - // rotate by 90 degrees counterclockwise around centroid - // and shrinking by 1/2 - // but no effect - let requested_vertex_1 = [ - -0.5 * (vertices[1][1] - centroid[1]) + centroid[0], - 0.5 * (vertices[1][0] - centroid[0]) + centroid[1], - ]; + // // since a different vertex is attracted to point (1,9), moves one up and to the right + // vertices = vertices.map((v) => [v[0] + 1, v[1] + 1]); - await win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 1: requested_vertex_1 }, - }, - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g3/pg", + // args: { + // pointCoords: { 2: requested_vertex_2 }, + // }, + // }); - testPolygonCopiedTwice({ vertices }); - }); + // testPolygonCopiedTwice({ vertices }); + // }); + // }); - cy.log("move copied polygon up does not move"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; + // it("Non-rigid polygon, three vertex constraints", () => { + // cy.window().then(async (win) => { + // win.postMessage( + // { + // doenetML: ` + // a + // + // (3,7) + // (-4,-1) + // (8,2) + // (-3,4) - // this translation will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - requested_vertices.push([ - vertices[i][0] + moveX, - vertices[i][1] + moveY, - ]); - } + // (1,9) + // (5,-1) + // (-9,5) + // + // + // $a1$a2$a3 + // + // + // + // + // $(../g1/pg{name="pg"}) + // $pg.vertices{assignNames="v1 v2 v3 v4"} + // + // $g2{name="g3"} + // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) + // `, + // }, + // "*", + // ); + // }); + // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - await win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); + // let vertices = [ + // [3, 7], + // [-4, -1], + // [8, 2], + // [-3, 4], + // ]; - testPolygonCopiedTwice({ vertices }); - }); + // testPolygonCopiedTwice({ vertices }); - cy.log("move double copied individual vertex doesn't move"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; + // cy.log("move individual vertex, attracts to closest point"); + // cy.window().then(async (win) => { + // let requested_vertex_1 = [-10, 6]; - // rotate by 180 degrees around centroid - // and doubling length - // but no effect - let requested_vertex_2 = [ - -2 * (vertices[2][0] - centroid[0]) + centroid[0], - -2 * (vertices[2][1] - centroid[1]) + centroid[1], - ]; + // vertices[1] = [-9, 5]; + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g1/pg", + // args: { + // pointCoords: { 1: requested_vertex_1 }, + // }, + // }); - await win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); + // testPolygonCopiedTwice({ vertices }); + // }); - testPolygonCopiedTwice({ vertices }); - }); + // cy.log("Moving entire polygon up attract to another point"); - cy.log("moving single copied vertex doesn't move"); - cy.window().then(async (win) => { - let centroid = vertices.reduce( - (a, c) => [a[0] + c[0], a[1] + c[1]], - [0, 0], - ); - centroid[0] /= 4; - centroid[1] /= 4; + // cy.window().then(async (win) => { + // let moveX = -1; + // let moveY = 1; - // rotate by 90 degrees clockwise around centroid - // and shrinking by 1/4 - // but no effect - let requested_vertex_3 = [ - 0.25 * (vertices[3][1] - centroid[1]) + centroid[0], - -0.25 * (vertices[3][0] - centroid[0]) + centroid[1], - ]; + // let requested_vertices = []; + // for (let i = 0; i < vertices.length; i++) { + // vertices[i][0] = vertices[i][0] + moveX; + // vertices[i][1] = vertices[i][1] + moveY; + // requested_vertices.push([vertices[i][0], vertices[i][1]]); + // } - await win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); + // // since attracted to point (1,9), moves one up and to the left + // vertices = vertices.map((v) => [v[0] - 1, v[1] + 1]); - testPolygonCopiedTwice({ vertices }); - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g2/pg", + // args: { + // pointCoords: requested_vertices, + // }, + // }); - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; + // testPolygonCopiedTwice({ vertices }); + // }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); + // cy.log("move double copied individual vertex"); + // cy.window().then(async (win) => { + // vertices[2] = [2, 1]; - testPolygonCopiedTwice({ vertices }); - }); - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g3/pg", + // args: { + // pointCoords: { 2: vertices[2] }, + // }, + // }); - it("Rotate around vertex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load + // testPolygonCopiedTwice({ vertices }); + // }); - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; + // cy.log("Moving entire polygon near two points, attracts to just one"); + // cy.window().then(async (win) => { + // let moveX = 2.6; + // let moveY = -2; - testPolygonCopiedTwice({ vertices }); + // let requested_vertices = []; + // for (let i = 0; i < vertices.length; i++) { + // vertices[i][0] = vertices[i][0] + moveX; + // vertices[i][1] = vertices[i][1] + moveY; + // requested_vertices.push([vertices[i][0], vertices[i][1]]); + // } - cy.log("move individual vertex rotates and dilates"); - cy.window().then(async (win) => { - let rotationPoint = vertices[1]; + // // since attracted to point (5,-1), moves 0.4 to the right + // vertices = vertices.map((v) => [v[0] + 0.4, v[1]]); - // rotate by 90 degrees counterclockwise around rotationPoint - // and shrinking by 1/2 - let requested_vertex_0 = [ - -0.5 * (vertices[0][1] - rotationPoint[1]) + rotationPoint[0], - 0.5 * (vertices[0][0] - rotationPoint[0]) + rotationPoint[1], - ]; - vertices = vertices.map((v) => [ - -0.5 * (v[1] - rotationPoint[1]) + rotationPoint[0], - 0.5 * (v[0] - rotationPoint[0]) + rotationPoint[1], - ]); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g2/pg", + // args: { + // pointCoords: requested_vertices, + // }, + // }); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 0: requested_vertex_0 }, - }, - }); + // testPolygonCopiedTwice({ vertices }); + // }); - testPolygonCopiedTwice({ vertices }); - }); + // cy.log( + // "Moving just one vertex attracts to other nearby vertex to attractor", + // ); + // cy.window().then(async (win) => { + // let requested_vertex_0 = [0, 10]; + // vertices[0] = [1, 9]; + // vertices[1] = [-9, 5]; - cy.log("move copied polygon up and to the right chooses minimum moved"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; + // win.callAction1({ + // actionName: "movePoint", + // componentName: "/g2/v1", + // args: { x: requested_vertex_0[0], y: requested_vertex_0[1] }, + // }); - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } + // testPolygonCopiedTwice({ vertices }); + // }); + // }); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); + // it("Rigid polygon, vertices attracted to polygon", () => { + // cy.window().then(async (win) => { + // win.postMessage( + // { + // doenetML: ` + // a + // + // - testPolygonCopiedTwice({ vertices }); - }); + // (-1,0) + // (3,0) + // (1,-3) + // + // + // $pa + // + // + // + // + // $(../g1/pg{name="pg"}) + // + // $g2{name="g3"} + // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) + // `, + // }, + // "*", + // ); + // }); + // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - cy.log( - "move double copied individual vertex, getting rotation and dilation", - ); - cy.window().then(async (win) => { - let rotationPoint = vertices[1]; + // cy.log("start shifted so that two vertices are attracted"); - // rotate by 180 degrees around rotationPoint - // and doubling length - let requested_vertex_2 = [ - -2 * (vertices[2][0] - rotationPoint[0]) + rotationPoint[0], - -2 * (vertices[2][1] - rotationPoint[1]) + rotationPoint[1], - ]; - vertices = vertices.map((v) => [ - -2 * (v[0] - rotationPoint[0]) + rotationPoint[0], - -2 * (v[1] - rotationPoint[1]) + rotationPoint[1], - ]); + // let vertices = [ + // [0, 0], + // [4, 0], + // [2, -3], + // ]; - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); + // testPolygonCopiedTwice({ vertices }); - testPolygonCopiedTwice({ vertices }); - }); + // cy.log("move individual vertex rotates, attracts to edge of polygon"); - cy.log("moving single copied vertex gets rotation and dilation"); - cy.window().then(async (win) => { - let rotationPoint = vertices[1]; + // let centroid = vertices.reduce( + // (a, c) => [a[0] + c[0], a[1] + c[1]], + // [0, 0], + // ); + // centroid[0] /= 3; + // centroid[1] /= 3; - // rotate by 90 degrees clockwise around rotationPoint - // and shrinking by 1/4 - let requested_vertex_3 = [ - 0.25 * (vertices[3][1] - rotationPoint[1]) + rotationPoint[0], - -0.25 * (vertices[3][0] - rotationPoint[0]) + rotationPoint[1], - ]; - vertices = vertices.map((v) => [ - 0.25 * (v[1] - rotationPoint[1]) + rotationPoint[0], - -0.25 * (v[0] - rotationPoint[0]) + rotationPoint[1], - ]); + // cy.window().then(async (win) => { + // // shift 1 to left to give original before attraction + // centroid[0] -= 1; + // vertices = vertices.map((v) => [v[0] - 1, v[1]]); - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); + // // rotate by 90 degrees clockwise around centroid + // // (shrinking by 1/2, but that will be ignored) + // let requested_vertex_1 = [ + // 0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + // -0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + // ]; + // vertices = vertices.map((v) => [ + // v[1] - centroid[1] + centroid[0], + // -(v[0] - centroid[0]) + centroid[1], + // ]); + // // since attracted to edge, moves down one and to the left + // vertices = vertices.map((v) => [v[0], v[1] - 1]); - testPolygonCopiedTwice({ vertices }); - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g1/pg", + // args: { + // pointCoords: { 1: requested_vertex_1 }, + // }, + // }); - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; + // testPolygonCopiedTwice({ vertices }); + // }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); + // cy.log("move copied polygon up and to the right"); + // cy.window().then(async (win) => { + // // Move so that bottom right gets attracted to (4,6). + // // Slope of orthogonal to attractor edge is -6/9. + // // So move bottom right to (4,6) + (9,-6)/10 - testPolygonCopiedTwice({ vertices }); - }); - }); + // let requested_bottom_right = [4 + 0.9, 6 - 0.6]; + // let actual_bottom_right = [4, 6]; - it("Rotate around exterior point", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,7) - (-4,-1) - (8,2) - (-3,4) - (-1,3) - + // let moveX = requested_bottom_right[0] - vertices[1][0]; + // let moveY = requested_bottom_right[1] - vertices[1][1]; - - - $(../g1/pg{name="pg"}) - $pg.vertices{assignNames="v1 v2 v3 v4"} - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load + // // add extra movement to requested vertices, which will be ignored + // let requested_vertices = []; + // for (let i = 0; i < vertices.length; i++) { + // vertices[i][0] = vertices[i][0] + moveX; + // vertices[i][1] = vertices[i][1] + moveY; + // requested_vertices.push([ + // vertices[i][0] + i, + // vertices[i][1] + 2 * i, + // ]); + // } - let vertices = [ - [3, 7], - [-4, -1], - [8, 2], - [-3, 4], - ]; + // // since attracted to point, moves up one and to the left + // vertices = vertices.map((v) => [ + // v[0] + actual_bottom_right[0] - requested_bottom_right[0], + // v[1] + actual_bottom_right[1] - requested_bottom_right[1], + // ]); - testPolygonCopiedTwice({ vertices }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g2/pg", + // args: { + // pointCoords: requested_vertices, + // }, + // }); - cy.log("move individual vertex rotates and dilates"); - cy.window().then(async (win) => { - let rotationPoint = [-1, 3]; + // testPolygonCopiedTwice({ vertices }); + // }); + // }); - // rotate by 90 degrees counterclockwise around rotationPoint - // and shrinking by 1/2 - let requested_vertex_0 = [ - -0.5 * (vertices[0][1] - rotationPoint[1]) + rotationPoint[0], - 0.5 * (vertices[0][0] - rotationPoint[0]) + rotationPoint[1], - ]; - vertices = vertices.map((v) => [ - -0.5 * (v[1] - rotationPoint[1]) + rotationPoint[0], - 0.5 * (v[0] - rotationPoint[0]) + rotationPoint[1], - ]); + // it("Rigid polygon, vertices attracted to polyline", () => { + // cy.window().then(async (win) => { + // win.postMessage( + // { + // doenetML: ` + // a + // + // - win.callAction1({ - actionName: "movePolygon", - componentName: "/g1/pg", - args: { - pointCoords: { 0: requested_vertex_0 }, - }, - }); + // (-1,0) + // (3,0) + // (1,-3) + // + // + // $pa + // + // + // + // + // $(../g1/pg{name="pg"}) + // + // $g2{name="g3"} + // $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) + // `, + // }, + // "*", + // ); + // }); + // cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - testPolygonCopiedTwice({ vertices }); - }); + // cy.log("start shifted so that two vertices are attracted"); - cy.log("move copied polygon up and to the right chooses minimum moved"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; + // let vertices = [ + // [0, 0], + // [4, 0], + // [2, -3], + // ]; - // add extra movement to requested vertices, which will be ignored - let requested_vertices = []; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - requested_vertices.push([ - vertices[i][0] + i, - vertices[i][1] + 2 * i, - ]); - } + // testPolygonCopiedTwice({ vertices }); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g2/pg", - args: { - pointCoords: requested_vertices, - }, - }); + // cy.log("move individual vertex rotates, attracts to edge of polygon"); - testPolygonCopiedTwice({ vertices }); - }); + // let centroid = vertices.reduce( + // (a, c) => [a[0] + c[0], a[1] + c[1]], + // [0, 0], + // ); + // centroid[0] /= 3; + // centroid[1] /= 3; - cy.log( - "move double copied individual vertex, getting rotation and dilation", - ); - cy.window().then(async (win) => { - let rotationPoint = [-1, 3]; + // cy.window().then(async (win) => { + // // shift 1 to left to give original before attraction + // centroid[0] -= 1; + // vertices = vertices.map((v) => [v[0] - 1, v[1]]); - // rotate by 180 degrees around rotationPoint - // and doubling length - let requested_vertex_2 = [ - -2 * (vertices[2][0] - rotationPoint[0]) + rotationPoint[0], - -2 * (vertices[2][1] - rotationPoint[1]) + rotationPoint[1], - ]; - vertices = vertices.map((v) => [ - -2 * (v[0] - rotationPoint[0]) + rotationPoint[0], - -2 * (v[1] - rotationPoint[1]) + rotationPoint[1], - ]); + // // rotate by 90 degrees clockwise around centroid + // // (shrinking by 1/2, but that will be ignored) + // let requested_vertex_1 = [ + // 0.5 * (vertices[1][1] - centroid[1]) + centroid[0], + // -0.5 * (vertices[1][0] - centroid[0]) + centroid[1], + // ]; + // vertices = vertices.map((v) => [ + // v[1] - centroid[1] + centroid[0], + // -(v[0] - centroid[0]) + centroid[1], + // ]); + // // since attracted to edge, moves down one and to the left + // vertices = vertices.map((v) => [v[0], v[1] - 1]); - win.callAction1({ - actionName: "movePolygon", - componentName: "/g3/pg", - args: { - pointCoords: { 2: requested_vertex_2 }, - }, - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g1/pg", + // args: { + // pointCoords: { 1: requested_vertex_1 }, + // }, + // }); - testPolygonCopiedTwice({ vertices }); - }); + // testPolygonCopiedTwice({ vertices }); + // }); - cy.log( - "change rotation point, then moving single copied vertex gets rotation and dilation", - ); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/g1/rotationPoint", - args: { x: 6, y: -2 }, - }); + // cy.log("move copied polygon up and to the right"); + // cy.window().then(async (win) => { + // // Move so that bottom right would get attracted to (4,6) if it where a polygon. + // // But since it is a polyline, that edge doesn't exist + // // and instead the upper right gets attracted to other edge. - let rotationPoint = [6, -2]; + // // If had polygon, + // // slope of orthogonal to attractor edge would be -6/9. + // // So move bottom right to (4,6) + (9,-6)/10 - // rotate by 90 degrees clockwise around rotationPoint - // and shrinking by 1/4 - let requested_vertex_3 = [ - 0.25 * (vertices[3][1] - rotationPoint[1]) + rotationPoint[0], - -0.25 * (vertices[3][0] - rotationPoint[0]) + rotationPoint[1], - ]; - vertices = vertices.map((v) => [ - 0.25 * (v[1] - rotationPoint[1]) + rotationPoint[0], - -0.25 * (v[0] - rotationPoint[0]) + rotationPoint[1], - ]); + // let requested_bottom_right = [4 + 0.9, 6 - 0.6]; + // let actual_bottom_right = [6, 5]; - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/v4", - args: { x: requested_vertex_3[0], y: requested_vertex_3[1] }, - }); + // let moveX = requested_bottom_right[0] - vertices[1][0]; + // let moveY = requested_bottom_right[1] - vertices[1][1]; - testPolygonCopiedTwice({ vertices }); - }); + // // add extra movement to requested vertices, which will be ignored + // let requested_vertices = []; + // for (let i = 0; i < vertices.length; i++) { + // vertices[i][0] = vertices[i][0] + moveX; + // vertices[i][1] = vertices[i][1] + moveY; + // requested_vertices.push([ + // vertices[i][0] + i, + // vertices[i][1] + 2 * i, + // ]); + // } - cy.log("moving defining vertex deforms polygon"); - cy.window().then(async (win) => { - vertices[0] = [4, 6]; + // // since attracted to point, moves up one and to the left + // vertices = vertices.map((v) => [ + // v[0] + actual_bottom_right[0] - requested_bottom_right[0], + // v[1] + actual_bottom_right[1] - requested_bottom_right[1], + // ]); - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/_point1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); + // win.callAction1({ + // actionName: "movePolygon", + // componentName: "/g2/pg", + // args: { + // pointCoords: requested_vertices, + // }, + // }); - testPolygonCopiedTwice({ vertices }); - }); - }); + // testPolygonCopiedTwice({ vertices }); + // }); + // }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/polyline.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/polyline.cy.js index 42718d616..c4671b4fc 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/polyline.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/polyline.cy.js @@ -1,4595 +1,9 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; +import { cesc } from "@doenet/utils"; -function nInDOM(n) { - if (n < 0) { - return `βˆ’${Math.abs(n)}`; - } else { - return String(n); - } -} - -async function testPolylineCopiedTwice({ - vertices, - polylineName = "/pg", - graph1Name = "/g1", - graph2Name = "/g2", - graph3Name = "/g3", - pointsInDomPrefix = "/p", -}) { - for (let i in vertices) { - let ind = Number(i) + 1; - if (Number.isFinite(vertices[i][0])) { - cy.get(`#${cesc2(pointsInDomPrefix + ind)} .mjx-mrow`).should( - "contain.text", - `(${nInDOM( - Math.round(vertices[i][0] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - } - if (Number.isFinite(vertices[i][1])) { - cy.get(`#${cesc2(pointsInDomPrefix + ind)} .mjx-mrow`).should( - "contain.text", - `,${nInDOM( - Math.round(vertices[i][1] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - } - } - cy.get(`#${cesc2(pointsInDomPrefix + (vertices.length + 1))}`).should( - "not.exist", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[graph1Name + polylineName].stateValues.numVertices, - ).eqls(vertices.length); - expect( - stateVariables[graph2Name + polylineName].stateValues.numVertices, - ).eqls(vertices.length); - expect( - stateVariables[graph3Name + polylineName].stateValues.numVertices, - ).eqls(vertices.length); - - for (let i in vertices) { - if (Number.isFinite(vertices[i][0])) { - expect( - me - .fromAst( - stateVariables[graph1Name + polylineName] - .stateValues.vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - expect( - me - .fromAst( - stateVariables[graph2Name + polylineName] - .stateValues.vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - expect( - me - .fromAst( - stateVariables[graph3Name + polylineName] - .stateValues.vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - } else { - expect( - stateVariables[graph1Name + polylineName].stateValues - .vertices[i][0], - ).eq(vertices[i][0]); - expect( - stateVariables[graph2Name + polylineName].stateValues - .vertices[i][0], - ).eq(vertices[i][0]); - expect( - stateVariables[graph3Name + polylineName].stateValues - .vertices[i][0], - ).eq(vertices[i][0]); - } - if (Number.isFinite(vertices[i][1])) { - expect( - me - .fromAst( - stateVariables[graph1Name + polylineName] - .stateValues.vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - expect( - me - .fromAst( - stateVariables[graph2Name + polylineName] - .stateValues.vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - expect( - me - .fromAst( - stateVariables[graph3Name + polylineName] - .stateValues.vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - } else { - expect( - stateVariables[graph1Name + polylineName].stateValues - .vertices[i][1], - ).eq(vertices[i][1]); - expect( - stateVariables[graph2Name + polylineName].stateValues - .vertices[i][1], - ).eq(vertices[i][1]); - expect( - stateVariables[graph3Name + polylineName].stateValues - .vertices[i][1], - ).eq(vertices[i][1]); - } - } - }); -} - -describe("Polyline Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("Polyline vertices and copied points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,5) - (-4,-1) - (5,2) - (-3,4) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 5], - [-4, -1], - [5, 2], - [-3, 4], - ]; - - testPolylineCopiedTwice({ vertices }); - - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move copied polyline up and to the right"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move double copied individual vertex"); - cy.window().then(async (win) => { - vertices[2] = [-9, -8]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g3/pg", - args: { - pointCoords: { 2: vertices[2] }, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - }); - - it("Polyline string points in vertices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -1 - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 5], - [-4, -1], - [5, 2], - [-3, 4], - ]; - - testPolylineCopiedTwice({ vertices }); - - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move copied polyline up and to the right"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move double copied individual vertex"); - cy.window().then(async (win) => { - vertices[2] = [-9, -8]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g3/pg", - args: { - pointCoords: { 2: vertices[2] }, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - }); - - it("dynamic polyline with vertices from copied map, initially zero, copied", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = []; - testPolylineCopiedTwice({ vertices }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}1{enter}", { force: true }) - .then(() => { - vertices[0] = [0, 5 * Math.sin(0)]; - testPolylineCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - vertices[1] = [1, 5 * Math.sin(1)]; - testPolylineCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}3{enter}", { force: true }) - .then(() => { - vertices[2] = [2, 5 * Math.sin(2)]; - testPolylineCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - vertices.splice(2, 1); - testPolylineCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}0{enter}", { force: true }) - .then(() => { - vertices = []; - testPolylineCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}5{enter}", { force: true }) - .then(() => { - for (let i = 0; i < 5; i++) { - vertices.push([i, 5 * Math.sin(i)]); - } - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("start over and begin with big increment"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b - - - - - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "b"); //wait for page to load - - cy.window().then(async (win) => { - vertices = []; - testPolylineCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}10{enter}", { force: true }) - .then(() => { - for (let i = 0; i < 10; i++) { - vertices.push([i, 5 * Math.sin(i)]); - } - testPolylineCopiedTwice({ vertices }); - }); - - cy.get(cesc("#\\/length") + " textarea") - .type("{end}{backspace}{backspace}1{enter}", { force: true }) - .then(() => { - vertices = [[0, 5 * Math.sin(0)]]; - testPolylineCopiedTwice({ vertices }); - }); - }); - - it("polyline with initially undefined point", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [1, 2], - [-1, 5], - ["\uff3f", 7], - [3, -5], - [-4, -3], - ]; - testPolylineCopiedTwice({ vertices }); - - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type("{end}{backspace}-2{enter}", { force: true }) - .then(() => { - vertices[2][0] = -2; - testPolylineCopiedTwice({ vertices }); - }); - }); - - it(`can't move polyline based on map`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - - $ti.value{assignNames="t"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = []; - for (let i = -5; i <= 5; i++) { - vertices.push([i, 5 * Math.sin(i)]); - } - testPolylineCopiedTwice({ vertices }); - - cy.log("can't move points"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/mp1", - args: { x: 9, y: -8 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/mp9", - args: { x: -8, y: 4 }, - }); - - // since core could be delayed and we can't tell that no change occurred, - // change value of textinput and wait for the change to be processed by core - cy.get(cesc("#\\/ti_input")).type("wait{enter}"); - cy.get(cesc("#\\/t")) - .should("have.text", "wait") - .then(() => { - testPolylineCopiedTwice({ vertices }); - }); - }); - - cy.log("can't move polyline1"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - let vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g1/pg", - args: { - pointCoords: vertices2, - }, - }); - - cy.get(cesc("#\\/ti_input")).clear().type("more{enter}"); - cy.get(cesc("#\\/t")) - .should("have.text", "more") - .then(() => { - testPolylineCopiedTwice({ vertices }); - }); - }); - - cy.log("can't move polyline2"); - cy.window().then(async (win) => { - let moveX = -5; - let moveY = 6; - - let vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices2, - }, - }); - - cy.get(cesc("#\\/ti_input")).clear().type("less{enter}"); - cy.get(cesc("#\\/t")) - .should("have.text", "less") - .then(() => { - testPolylineCopiedTwice({ vertices }); - }); - }); - - cy.log("can't move polyline3"); - cy.window().then(async (win) => { - let moveX = 7; - let moveY = -4; - - let vertices2 = vertices.map((v) => [v[0] + moveX, v[1] + moveY]); - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g3/pg", - args: { - pointCoords: vertices2, - }, - }); - - cy.get(cesc("#\\/ti_input")).clear().type("last{enter}"); - cy.get(cesc("#\\/t")) - .should("have.text", "last") - .then(() => { - testPolylineCopiedTwice({ vertices }); - }); - }); - }); - - it(`create moveable polyline based on map`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - - - $(g1/pg.vertices) - - - $ti.value{assignNames="t"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = []; - for (let i = -5; i <= 5; i++) { - vertices.push([i, 5 * Math.sin(i)]); - } - testPolylineCopiedTwice({ vertices }); - - cy.log("can move points"); - - cy.window().then(async (win) => { - vertices[0] = [9, -8]; - vertices[8] = [-8, 4]; - - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/mp1", - args: { x: vertices[0][0], y: vertices[0][1] }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/mp9", - args: { x: vertices[8][0], y: vertices[8][1] }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("can move polyline1"); - cy.window().then(async (win) => { - let moveX = 3; - let moveY = 2; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g1/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("can move polyline2"); - cy.window().then(async (win) => { - let moveX = -5; - let moveY = 6; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("can move polyline3"); - cy.window().then(async (win) => { - let moveX = 7; - let moveY = -4; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - }); - - it("copy vertices of polyline", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_polyline1.vertex1{assignNames="v1"} - $_polyline1.vertex2{assignNames="v2"} - $_polyline1.vertex3{assignNames="v3"} - $_polyline1.vertex4{assignNames="v4"} - - - - - $_polyline1.vertex4{assignNames="v4b"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let ps = [ - [-3, -1], - [1, 2], - [3, 4], - [6, -2], - ]; - - for (let i = 0; i < 4; i++) { - expect(stateVariables[`/v${i + 1}`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}`].stateValues.xs[1]).eq( - ps[i][1], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1]).eq( - ps[i][1], - ); - } - - cy.get(cesc("#\\/v4b") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(ps[3][0])},${nInDOM(ps[3][1])})`, - ); - }); - - cy.log("move individually copied vertices"); - cy.window().then(async (win) => { - let ps = [ - [-5, 3], - [-2, 7], - [0, -8], - [9, -6], - ]; - - for (let i = 0; i < 4; i++) { - win.callAction1({ - actionName: "movePoint", - componentName: `/v${i + 1}`, - args: { x: ps[i][0], y: ps[i][1] }, - }); - } - - cy.get(cesc("#\\/v4b") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(ps[3][0])},${nInDOM(ps[3][1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 0; i < 4; i++) { - expect(stateVariables[`/v${i + 1}`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}`].stateValues.xs[1]).eq( - ps[i][1], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1]).eq( - ps[i][1], - ); - } - }); - }); - - cy.log("move array-copied vertices"); - cy.window().then(async (win) => { - let ps = [ - [-7, -1], - [-3, 5], - [2, 4], - [6, 0], - ]; - - for (let i = 0; i < 4; i++) { - win.callAction1({ - actionName: "movePoint", - componentName: `/v${i + 1}a`, - args: { x: ps[i][0], y: ps[i][1] }, - }); - } - - cy.get(cesc("#\\/v4b") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(ps[3][0])},${nInDOM(ps[3][1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 0; i < 4; i++) { - expect(stateVariables[`/v${i + 1}`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[0]).eq( - ps[i][0], - ); - expect(stateVariables[`/v${i + 1}`].stateValues.xs[1]).eq( - ps[i][1], - ); - expect(stateVariables[`/v${i + 1}a`].stateValues.xs[1]).eq( - ps[i][1], - ); - } - }); - }); - }); - - it("new polyline from copied vertices of polyline", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [-9, 6], - [-3, 7], - [4, 0], - [8, 5], - ]; - - testPolylineCopiedTwice({ vertices }); - - cy.log("move first polyline up and to the right"); - cy.window().then(async (win) => { - let moveX = 4; - let moveY = 2; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g1/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move copied polyline up and to the left"); - cy.window().then(async (win) => { - let moveX = -7; - let moveY = 3; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move dobule copied polyline down and to the left"); - cy.window().then(async (win) => { - let moveX = -1; - let moveY = -4; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] += moveX; - vertices[i][1] += moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g3/pg", - args: { - pointCoords: vertices, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - }); - - it("new polyline as translated version of polyline", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - $_polyline1.vertices{name="vs"} - - - - - $_polyline2.vertices{assignNames="p1 p2 p3 p4"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - async function testPolylines({ vertices, transX, transY }) { - let vertices2 = vertices.map((v) => [v[0] + transX, v[1] + transY]); - - for (let i in vertices) { - let ind = Number(i) + 1; - cy.get(`#${cesc2("/p" + ind)} .mjx-mrow`).should( - "contain.text", - `(${nInDOM( - Math.round(vertices2[i][0] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - cy.get(`#${cesc2("/p" + ind)} .mjx-mrow`).should( - "contain.text", - `,${nInDOM( - Math.round(vertices2[i][1] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - } - cy.get(`#${cesc2("/p" + (vertices.length + 1))}`).should( - "not.exist", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.numVertices, - ).eqls(vertices.length); - expect( - stateVariables["/_polyline2"].stateValues.numVertices, - ).eqls(vertices.length); - - for (let i in vertices) { - if (Number.isFinite(vertices[i][0])) { - expect( - me - .fromAst( - stateVariables["/_polyline1"].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - expect( - me - .fromAst( - stateVariables["/_polyline2"].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices2[i][0], 1e-12); - } else { - expect( - stateVariables["/_polyline1"].stateValues.vertices[ - i - ][0], - ).eq(vertices[i][0]); - expect( - stateVariables["/_polyline2"].stateValues.vertices[ - i - ][0], - ).eq(vertices2[i][0]); - } - if (Number.isFinite(vertices[i][1])) { - expect( - me - .fromAst( - stateVariables["/_polyline1"].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - expect( - me - .fromAst( - stateVariables["/_polyline2"].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices2[i][1], 1e-12); - } else { - expect( - stateVariables["/_polyline1"].stateValues.vertices[ - i - ][1], - ).eq(vertices[i][1]); - expect( - stateVariables["/_polyline2"].stateValues.vertices[ - i - ][1], - ).eq(vertices2[i][1]); - } - } - }); - } - - let vertices = [ - [0, 0], - [3, -4], - [1, -6], - [-5, -6], - ]; - let transX = 5; - let transY = 7; - - testPolylines({ vertices, transX, transY }); - - cy.log("move points on first polyline"); - cy.window().then(async (win) => { - vertices = [ - [1, -1], - [-3, 2], - [-1, 7], - [6, 3], - ]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: vertices, - }, - }); - - testPolylines({ vertices, transX, transY }); - }); - - cy.log("move points on second polyline"); - cy.window().then(async (win) => { - let vertices2 = [ - [-3, 4], - [1, 0], - [9, 6], - [2, -1], - ]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline2", - args: { - pointCoords: vertices2, - }, - }); - - vertices = vertices2.map((v) => [v[0] - transX, v[1] - transY]); - - testPolylines({ vertices, transX, transY }); - }); - - cy.log("change translation"); - cy.get(cesc("#\\/transx") + " textarea").type( - "{end}{backspace}2{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/transy") + " textarea").type( - "{end}{backspace}10{enter}", - { - force: true, - }, - ); - cy.window().then(async (win) => { - transX = 2; - transY = 10; - - testPolylines({ vertices, transX, transY }); - }); - }); - - it("open parallelogram based on three points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $parallelogram.vertices{assignNames="p1 p2 p3 p4"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - let D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/parallelogram", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/parallelogram", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - D = [A[0] + C[0] - B[0], A[1] + C[1] - B[1]]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/parallelogram", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - D = [7, 0]; - B = [A[0] + C[0] - D[0], A[1] + C[1] - D[1]]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/parallelogram", - args: { - pointCoords: { 3: D }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/parallelogram"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/parallelogram"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/parallelogram"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/parallelogram"].stateValues.vertices[3], - ).eqls(D); - }); - }); - }); - - it("new polyline from copied vertices, some flipped", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $_polyline2.vertices{assignNames="p1 p2 p3 p4"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - async function testPolylines({ vertices }) { - let vertices2 = [...vertices]; - vertices2[1] = [vertices2[1][1], vertices2[1][0]]; - vertices2[3] = [vertices2[3][1], vertices2[3][0]]; - - for (let i in vertices) { - let ind = Number(i) + 1; - cy.get(`#${cesc2("/p" + ind)} .mjx-mrow`).should( - "contain.text", - `(${nInDOM( - Math.round(vertices2[i][0] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - cy.get(`#${cesc2("/p" + ind)} .mjx-mrow`).should( - "contain.text", - `,${nInDOM( - Math.round(vertices2[i][1] * 100000000) / 100000000, - ).substring(0, 6)}`, - ); - } - cy.get(`#${cesc2("/p" + (vertices.length + 1))}`).should( - "not.exist", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.numVertices, - ).eqls(vertices.length); - expect( - stateVariables["/_polyline2"].stateValues.numVertices, - ).eqls(vertices.length); - - for (let i in vertices) { - if (Number.isFinite(vertices[i][0])) { - expect( - me - .fromAst( - stateVariables["/_polyline1"].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][0], 1e-12); - expect( - me - .fromAst( - stateVariables["/_polyline2"].stateValues - .vertices[i][0], - ) - .evaluate_to_constant(), - ).closeTo(vertices2[i][0], 1e-12); - } else { - expect( - stateVariables["/_polyline1"].stateValues.vertices[ - i - ][0], - ).eq(vertices[i][0]); - expect( - stateVariables["/_polyline2"].stateValues.vertices[ - i - ][0], - ).eq(vertices2[i][0]); - } - if (Number.isFinite(vertices[i][1])) { - expect( - me - .fromAst( - stateVariables["/_polyline1"].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices[i][1], 1e-12); - expect( - me - .fromAst( - stateVariables["/_polyline2"].stateValues - .vertices[i][1], - ) - .evaluate_to_constant(), - ).closeTo(vertices2[i][1], 1e-12); - } else { - expect( - stateVariables["/_polyline1"].stateValues.vertices[ - i - ][1], - ).eq(vertices[i][1]); - expect( - stateVariables["/_polyline2"].stateValues.vertices[ - i - ][1], - ).eq(vertices2[i][1]); - } - } - }); - } - - let vertices = [ - [-9, 6], - [-3, 7], - [4, 0], - [8, 5], - ]; - - testPolylines({ vertices }); - - cy.log("move first polyline verticies"); - cy.window().then(async (win) => { - vertices = [ - [7, 2], - [1, -3], - [2, 9], - [-4, -3], - ]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: vertices, - }, - }); - - testPolylines({ vertices }); - }); - - cy.log("move second polyline verticies"); - cy.window().then(async (win) => { - let vertices2 = [ - [-1, 9], - [5, 7], - [-8, 1], - [-7, 6], - ]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline2", - args: { - pointCoords: vertices2, - }, - }); - - vertices = [...vertices2]; - vertices[1] = [vertices[1][1], vertices[1][0]]; - vertices[3] = [vertices[3][1], vertices[3][0]]; - - testPolylines({ vertices }); - }); - }); - - it("four vertex polyline based on three points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_polyline1.vertices{assignNames="p1 p2 p3 p4"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - let D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_polyline1"].stateValues.vertices[0]).eqls( - A, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[1]).eqls( - B, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[2]).eqls( - C, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[3]).eqls( - D, - ); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - D = [C[0] + B[0] - A[0], C[1] + B[1] - A[1]]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(D); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - D = [7, 0]; - A = [C[0] + B[0] - D[0], C[1] + B[1] - D[1]]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 3: D }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(D); - }); - }); - }); - - it("fourth vertex depends on internal copy of first vertex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_polyline1.vertices{assignNames="p1 p2 p3 p4"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_polyline1"].stateValues.numVertices).eq(4); - expect(stateVariables["/_polyline1"].stateValues.vertices[0]).eqls( - A, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[1]).eqls( - B, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[2]).eqls( - C, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[3]).eqls( - A, - ); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 3: A }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - }); - - it("first vertex depends on internal copy of fourth vertex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_polyline1.vertices{assignNames="p1 p2 p3 p4"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_polyline1"].stateValues.numVertices).eq(4); - expect(stateVariables["/_polyline1"].stateValues.vertices[0]).eqls( - A, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[1]).eqls( - B, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[2]).eqls( - C, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[3]).eqls( - A, - ); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 3: A }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - }); - }); - }); - - it("first vertex depends fourth, formula for fifth", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_polyline1.vertices{assignNames="p1 p2 p3 p4 p5"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [1, 2]; - let B = [3, 4]; - let C = [-5, 6]; - let D = [A[0] + 1, 2]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_polyline1"].stateValues.vertices[0]).eqls( - A, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[1]).eqls( - B, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[2]).eqls( - C, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[3]).eqls( - A, - ); - expect(stateVariables["/_polyline1"].stateValues.vertices[4]).eqls( - D, - ); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -1]; - D[0] = A[0] + 1; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - D[0] = A[0] + 1; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 3: A }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - - cy.log("move fifth vertex"); - cy.window().then(async (win) => { - D = [-5, 9]; - A[0] = D[0] - 1; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 4: D }, - }, - }); - - cy.get(cesc("#\\/p5") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_polyline1"].stateValues.vertices[0], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[1], - ).eqls(B); - expect( - stateVariables["/_polyline1"].stateValues.vertices[2], - ).eqls(C); - expect( - stateVariables["/_polyline1"].stateValues.vertices[3], - ).eqls(A); - expect( - stateVariables["/_polyline1"].stateValues.vertices[4], - ).eqls(D); - }); - }); - }); - - it("first, fourth, seventh vertex depends on fourth, seventh, tenth", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $P.vertices{assignNames="p1 p2 p3 p4 p5 p6 p7 p8 p9 p10"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [-5, -1]; - let B = [1, 2]; - let C = [3, 4]; - let D = [5, 7]; - let E = [-5, 7]; - let F = [3, 1]; - let G = [5, 0]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -9]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 0: A }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 3: A }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move fifth vertex"); - cy.window().then(async (win) => { - D = [-9, 1]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 4: D }, - }, - }); - - cy.get(cesc("#\\/p5") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move sixth vertex"); - cy.window().then(async (win) => { - E = [-3, 6]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 5: E }, - }, - }); - - cy.get(cesc("#\\/p6") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(E[0])},${nInDOM(E[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move seventh vertex"); - cy.window().then(async (win) => { - A = [2, -4]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 6: A }, - }, - }); - - cy.get(cesc("#\\/p7") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move eighth vertex"); - cy.window().then(async (win) => { - F = [6, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 7: F }, - }, - }); - - cy.get(cesc("#\\/p8") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(F[0])},${nInDOM(F[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move nineth vertex"); - cy.window().then(async (win) => { - G = [1, -8]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 8: G }, - }, - }); - - cy.get(cesc("#\\/p9") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(G[0])},${nInDOM(G[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move tenth vertex"); - cy.window().then(async (win) => { - A = [-6, 10]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 9: A }, - }, - }); - - cy.get(cesc("#\\/p10") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - }); - - it("first, fourth, seventh vertex depends on shifted fourth, seventh, tenth", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $P.vertices{assignNames="p1 p2 p3 p4 p5 p6 p7 p8 p9 p10"} - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let A = [-5, -1]; - let B = [1, 2]; - let C = [3, 4]; - let D = [5, 7]; - let E = [-5, 7]; - let F = [3, 1]; - let G = [5, 0]; - let A1 = [A[0] + 1, A[1] + 1]; - let A2 = [A[0] + 2, A[1] + 2]; - let A3 = [A[0] + 3, A[1] + 3]; - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A3[0])},${nInDOM(A3[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - - cy.log("move first vertex"); - cy.window().then(async (win) => { - A = [-4, -9]; - A1 = [A[0] + 1, A[1] + 1]; - A2 = [A[0] + 2, A[1] + 2]; - A3 = [A[0] + 3, A[1] + 3]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 0: A3 }, - }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A3[0])},${nInDOM(A3[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move second vertex"); - cy.window().then(async (win) => { - B = [8, 9]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 1: B }, - }, - }); - - cy.get(cesc("#\\/p2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(B[0])},${nInDOM(B[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move third vertex"); - cy.window().then(async (win) => { - C = [-3, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 2: C }, - }, - }); - - cy.get(cesc("#\\/p3") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(C[0])},${nInDOM(C[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move fourth vertex"); - cy.window().then(async (win) => { - A = [7, 0]; - A1 = [A[0] + 1, A[1] + 1]; - A2 = [A[0] + 2, A[1] + 2]; - A3 = [A[0] + 3, A[1] + 3]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 3: A2 }, - }, - }); - - cy.get(cesc("#\\/p4") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A2[0])},${nInDOM(A2[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move fifth vertex"); - cy.window().then(async (win) => { - D = [-9, 1]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 4: D }, - }, - }); - - cy.get(cesc("#\\/p5") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(D[0])},${nInDOM(D[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move sixth vertex"); - cy.window().then(async (win) => { - E = [-3, 6]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 5: E }, - }, - }); - - cy.get(cesc("#\\/p6") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(E[0])},${nInDOM(E[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move seventh vertex"); - cy.window().then(async (win) => { - A = [2, -4]; - A1 = [A[0] + 1, A[1] + 1]; - A2 = [A[0] + 2, A[1] + 2]; - A3 = [A[0] + 3, A[1] + 3]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 6: A1 }, - }, - }); - - cy.get(cesc("#\\/p7") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A1[0])},${nInDOM(A1[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move eighth vertex"); - cy.window().then(async (win) => { - F = [6, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 7: F }, - }, - }); - - cy.get(cesc("#\\/p8") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(F[0])},${nInDOM(F[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move nineth vertex"); - cy.window().then(async (win) => { - G = [1, -8]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 8: G }, - }, - }); - - cy.get(cesc("#\\/p9") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(G[0])},${nInDOM(G[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - - cy.log("move tenth vertex"); - cy.window().then(async (win) => { - A = [-6, 7]; - A1 = [A[0] + 1, A[1] + 1]; - A2 = [A[0] + 2, A[1] + 2]; - A3 = [A[0] + 3, A[1] + 3]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/P", - args: { - pointCoords: { 9: A }, - }, - }); - - cy.get(cesc("#\\/p10") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(A[0])},${nInDOM(A[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.vertices[0]).eqls(A3); - expect(stateVariables["/P"].stateValues.vertices[1]).eqls(B); - expect(stateVariables["/P"].stateValues.vertices[2]).eqls(C); - expect(stateVariables["/P"].stateValues.vertices[3]).eqls(A2); - expect(stateVariables["/P"].stateValues.vertices[4]).eqls(D); - expect(stateVariables["/P"].stateValues.vertices[5]).eqls(E); - expect(stateVariables["/P"].stateValues.vertices[6]).eqls(A1); - expect(stateVariables["/P"].stateValues.vertices[7]).eqls(F); - expect(stateVariables["/P"].stateValues.vertices[8]).eqls(G); - expect(stateVariables["/P"].stateValues.vertices[9]).eqls(A); - }); - }); - }); - - it("attract to polyline", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_polyline1 - - - - $_point1{name="p1" displayDigits="8"} - $_polyline1.vertices{assignNames="v1 v2 v3" displayDigits="8"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let x1 = 3, - x2 = -4, - x3 = 5; - let y1 = 5, - y2 = -1, - y3 = 2; - - cy.log("point originally not attracted"); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", `(7,8)`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.coords).eqls([ - "vector", - 7, - 8, - ]); - }); - - cy.log("move point near segment 1"); - cy.window().then(async (win) => { - let x = 1; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(1.14`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move point near segment 2"); - cy.window().then(async (win) => { - let x = 3; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.4; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3.12`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - - cy.log("move point near segment between first and last vertices"); - cy.window().then(async (win) => { - let x = 4; - let mseg3 = (y1 - y3) / (x1 - x3); - let y = mseg3 * (x - x3) + y3 + 0.2; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", `(4,`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.log("move point just past first vertex"); - cy.window().then(async (win) => { - let x = x1 + 0.2; - let y = y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3,5)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x1, 1e-6); - expect(py).closeTo(y1, 1e-6); - }); - }); - - cy.log("point not attracted along extension of first segment"); - cy.window().then(async (win) => { - let x = 4; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", `(4,`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-5)},`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.log("move point just past second vertex"); - cy.window().then(async (win) => { - let x = x2 - 0.2; - let y = y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-4)},`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log("point not attracted along extension of second segment"); - cy.window().then(async (win) => { - let x = 6; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", `(6,`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-5)},`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x, 1e-6); - expect(py).closeTo(y, 1e-6); - }); - }); - - cy.log("move polyline so point attracts to first segment"); - cy.window().then(async (win) => { - let moveX = -3; - let moveY = -2; - - x1 += moveX; - x2 += moveX; - x3 += moveX; - y1 += moveY; - y2 += moveY; - y3 += moveY; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: [ - [x1, y1], - [x2, y2], - [x3, y3], - ], - }, - }); - - cy.get(cesc("#\\/v1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg1 = (y2 - y1) / (x2 - x1); - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move second vertex so point attracts to second segment"); - cy.window().then(async (win) => { - let moveX = -1; - let moveY = 1; - - x2 += moveX; - y2 += moveY; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 1: [x2, y2] }, - }, - }); - - cy.get(cesc("#\\/v2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg2 = (y2 - y3) / (x2 - x3); - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - }); - - it("constrain to polyline", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_polyline1 - - - - $_point1{name="p1" displayDigits="8"} - $_polyline1.vertices{assignNames="v1 v2 v3" displayDigits="8"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let x1 = 3, - x2 = -4, - x3 = 5; - let y1 = 5, - y2 = -1, - y3 = 2; - - cy.log("point originally constrained"); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - }); - - cy.log("move point near segment 1"); - cy.window().then(async (win) => { - let x = 1; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(1.14`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move point near segment 2"); - cy.window().then(async (win) => { - let x = 3; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.4; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3.12`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - - cy.log("move point near segment between first and last vertices"); - cy.window().then(async (win) => { - let x = 4; - let mseg3 = (y1 - y3) / (x1 - x3); - let y = mseg3 * (x - x3) + y3 + 0.2; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(2.93`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - let mseg1 = (y2 - y1) / (x2 - x1); - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move point just past first vertex"); - cy.window().then(async (win) => { - let x = x1 + 0.2; - let y = y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(3,5)`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x1, 1e-6); - expect(py).closeTo(y1, 1e-6); - }); - }); - - cy.log( - "point along extension of first segment constrained to endpoint", - ); - cy.window().then(async (win) => { - let x = 4; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x1, 1e-6); - expect(py).closeTo(y1, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg1 = (y2 - y1) / (x2 - x1); - let y = mseg1 * (x - x1) + y1 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log("move point just past second vertex"); - cy.window().then(async (win) => { - let x = x2 - 0.2; - let y = y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log( - "point along extension of second segment constrained to endpoint", - ); - cy.window().then(async (win) => { - let x = 6; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 + 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x3)},${nInDOM(y3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x3, 1e-6); - expect(py).closeTo(y3, 1e-6); - }); - }); - - cy.window().then(async (win) => { - let x = -5; - let mseg2 = (y2 - y3) / (x2 - x3); - let y = mseg2 * (x - x2) + y2 - 0.3; - - win.callAction1({ - actionName: "movePoint", - componentName: `/_point1`, - args: { x, y }, - }); - - cy.get(cesc("#\\/p1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - expect(px).closeTo(x2, 1e-6); - expect(py).closeTo(y2, 1e-6); - }); - }); - - cy.log("move polyline so point constrained to first segment"); - cy.window().then(async (win) => { - let moveX = -3; - let moveY = -5; - - x1 += moveX; - x2 += moveX; - x3 += moveX; - y1 += moveY; - y2 += moveY; - y3 += moveY; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: [ - [x1, y1], - [x2, y2], - [x3, y3], - ], - }, - }); - - cy.get(cesc("#\\/v1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg1 = (y2 - y1) / (x2 - x1); - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move second vertex so point constrained to second segment"); - cy.window().then(async (win) => { - let moveX = -1; - let moveY = 8; - - x2 += moveX; - y2 += moveY; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/_polyline1", - args: { - pointCoords: { 1: [x2, y2] }, - }, - }); - - cy.get(cesc("#\\/v2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let px = stateVariables["/_point1"].stateValues.xs[0]; - let py = stateVariables["/_point1"].stateValues.xs[1]; - - let mseg2 = (y2 - y3) / (x2 - x3); - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - }); - - it("constrain to polyline, different scales from graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $p - - - - $A{name="A2"} - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let x1 = -50, - x2 = -40, - x3 = 70, - x4 = 10; - let y1 = -0.02, - y2 = 0.07, - y3 = 0.06, - y4 = -0.01; - - cy.log("point originally on segment 3"); - - cy.get(cesc("#\\/A2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(15)}`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mseg3 = (y4 - y3) / (x4 - x3); - - let px = stateVariables["/A"].stateValues.xs[0]; - let py = stateVariables["/A"].stateValues.xs[1]; - - expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); - }); - - cy.log("move point near segment 1"); - cy.window().then(async (win) => { - let mseg1 = (y2 - y1) / (x2 - x1); - - win.callAction1({ - actionName: "movePoint", - componentName: `/A`, - args: { x: -20, y: 0.02 }, - }); - - cy.get(cesc("#\\/A2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(-45)}`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/A"].stateValues.xs[0]; - let py = stateVariables["/A"].stateValues.xs[1]; - - expect(py).closeTo(mseg1 * (px - x1) + y1, 1e-6); - }); - }); - - cy.log("move point near segment 2"); - cy.window().then(async (win) => { - let mseg2 = (y2 - y3) / (x2 - x3); - - win.callAction1({ - actionName: "movePoint", - componentName: `/A`, - args: { x: 0, y: 0.04 }, - }); - - cy.get(cesc("#\\/A2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(2.3)}`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/A"].stateValues.xs[0]; - let py = stateVariables["/A"].stateValues.xs[1]; - - expect(py).closeTo(mseg2 * (px - x2) + y2, 1e-6); - }); - }); - - cy.log("move point near segement between first and last vertices"); - cy.window().then(async (win) => { - let mseg3 = (y4 - y3) / (x4 - x3); - - win.callAction1({ - actionName: "movePoint", - componentName: `/A`, - args: { x: -10, y: 0.02 }, - }); - - cy.get(cesc("#\\/A2") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(16)}`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let px = stateVariables["/A"].stateValues.xs[0]; - let py = stateVariables["/A"].stateValues.xs[1]; - - expect(py).closeTo(mseg3 * (px - x3) + y3, 1e-6); - }); - }); - }); - - it("fixed polyline", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $ti.value{assignNames="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["/p"].stateValues.vertices[0]).eqls([1, 3]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.fixed).eq(true); - }); - - cy.log("cannot move vertices"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: [ - [4, 7], - [8, 10], - [1, 9], - ], - }, - }); - - // to make sure waited for core to react, - // wait for text to change from change in textinput - cy.get(cesc("#\\/ti_input")).type("wait{enter}"); - cy.get(cesc("#\\/t")).should("have.text", "wait"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([ - 1, 3, - ]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([ - 5, 7, - ]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([ - -2, 6, - ]); - }); - }); - }); - - it("copy propIndex of vertices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -

- -

- -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let t1x = 2, - t1y = -3; - let t2x = 3, - t2y = 4; - let t3x = -3, - t3y = 4; - - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t1x)},${nInDOM(t1y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2x)}`, - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t2x)},${nInDOM(t2y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2y)}`, - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t3x)},${nInDOM(t3y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - }); - - it("copy propIndex of vertices, dot and array notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -

- -

- -

- -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let t1x = 2, - t1y = -3; - let t2x = 3, - t2y = 4; - let t3x = -3, - t3y = 4; - - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t1x)},${nInDOM(t1y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2x)}`, - ); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2x)}`, - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t2x)},${nInDOM(t2y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2y)}`, - ); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should( - "contain.text", - `${nInDOM(t2y)}`, - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should( - "contain.text", - `(${nInDOM(t3x)},${nInDOM(t3y)})`, - ); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/xa") + " .mjx-mrow").should("not.exist"); - }); - - it("polyline from vector operations", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (-3,2) - - (2,1) - - - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’3,2)"); - cy.get(cesc2("#/P1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,βˆ’2)"); - cy.get(cesc2("#/P2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,3)"); - cy.get(cesc2("#/P3") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’4,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/polyline"].stateValues.vertices).eqls([ - [7, -2], - [6, 3], - [-4, 5], - ]); - }); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/polyline", - args: { - pointCoords: { 0: [3, 5] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(6,3)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’4,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/polyline"].stateValues.vertices).eqls([ - [3, 5], - [6, 3], - [-4, 5], - ]); - }); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/polyline", - args: { - pointCoords: { 1: [-9, -6] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(βˆ’9,βˆ’6)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’9,2)"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/polyline", - args: { - pointCoords: { 2: [-3, 1] }, - }, - }); - }); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(3,5)"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(9,βˆ’9)"); - cy.get(cesc2("#/P3") + " .mjx-mrow").should("contain.text", "(βˆ’3,1)"); - }); - - it("draggable, vertices draggable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - -

To wait:

-

draggable:

-

vertices draggable:

-

all vertices: $p.vertices

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([1, 3]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - - cy.log("cannot move single vertex"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: { 0: [4, 7] }, - }, - }); - }); - - // wait for core to process click - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/bi2")).should("have.text", "true"); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([1, 3]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - - cy.log("cannot move all vertices"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: [ - [4, 7], - [8, 10], - [1, 9], - ], - }, - }); - }); - - // wait for core to process click - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/bi2")).should("have.text", "false"); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([1, 3]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - - cy.log("only vertices draggable"); - - cy.get(cesc("#\\/verticesDraggable")).click(); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.log("can move single vertex"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: { 0: [4, 7] }, - }, - }); - }); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow").should( - "contain.text", - "(4,7)", - ); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([4, 7]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); - }); - - cy.log("cannot move all vertices"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: [ - [3, 8], - [8, 10], - [1, 9], - ], - }, - }); - }); - - // wait for core to process click - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/bi2")).should("have.text", "true"); - - cy.get(cesc("#\\/d2")).should("have.text", "false"); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([4, 7]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([5, 7]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(false); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); - }); - - cy.log("vertices and polyline draggable"); - - cy.get(cesc("#\\/draggable")).click(); - cy.get(cesc("#\\/d2")).should("have.text", "true"); - - cy.log("can move single vertex"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: { 1: [-3, 2] }, - }, - }); - }); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow").should( - "contain.text", - "(βˆ’3,2)", - ); - - cy.get(cesc("#\\/d2")).should("have.text", "true"); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,7)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(βˆ’3,2)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(βˆ’2,6)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([4, 7]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([-3, 2]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([-2, 6]); - expect(stateVariables["/p"].stateValues.draggable).eq(true); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); - }); - - cy.log("can move all vertices"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: [ - [3, 8], - [8, 10], - [1, 9], - ], - }, - }); - }); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow").should( - "contain.text", - "(3,8)", - ); - - cy.get(cesc("#\\/d2")).should("have.text", "true"); - cy.get(cesc("#\\/vd2")).should("have.text", "true"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,8)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(8,10)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(1,9)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([3, 8]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([8, 10]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([1, 9]); - expect(stateVariables["/p"].stateValues.draggable).eq(true); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq(true); - }); - - cy.log("polyline but not vertices draggable"); - - cy.get(cesc("#\\/verticesDraggable")).click(); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.log("cannot move single vertex"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: { 2: [9, 3] }, - }, - }); - }); - - // wait for core to process click - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/bi2")).should("have.text", "false"); - - cy.get(cesc("#\\/d2")).should("have.text", "true"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,8)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(8,10)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(1,9)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([3, 8]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([8, 10]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([1, 9]); - expect(stateVariables["/p"].stateValues.draggable).eq(true); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); - - cy.log("can move all vertices"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: [ - [-4, 1], - [9, -4], - [0, 7], - ], - }, - }); - }); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow").should( - "contain.text", - "(βˆ’4,1)", - ); - - cy.get(cesc("#\\/d2")).should("have.text", "true"); - cy.get(cesc("#\\/vd2")).should("have.text", "false"); - - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(0) - .should("have.text", "(βˆ’4,1)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(2) - .should("have.text", "(9,βˆ’4)"); - cy.get(cesc("#\\/pvert") + " .mjx-mrow") - .eq(4) - .should("have.text", "(0,7)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.vertices[0]).eqls([-4, 1]); - expect(stateVariables["/p"].stateValues.vertices[1]).eqls([9, -4]); - expect(stateVariables["/p"].stateValues.vertices[2]).eqls([0, 7]); - expect(stateVariables["/p"].stateValues.draggable).eq(true); - expect(stateVariables["/p"].stateValues.verticesDraggable).eq( - false, - ); - }); +describe("Polyline Tag Tests", function () { + beforeEach(() => { + cy.clearIndexedDB(); + cy.visit("/"); }); it("style description changes with theme", () => { @@ -4649,421 +63,4 @@ describe("Polyline Tag Tests", function () { "C is a thin white polyline.", ); }); - - it("One vertex constrained to grid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,5) - (-4,-1) - (5,2) - - - - - (-3,4) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 5], - [-4, -1], - [6, 4], - [-3, 4], - ]; - - testPolylineCopiedTwice({ vertices }); - - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move copied polyline up and to the right"); - cy.window().then(async (win) => { - let moveX = 4; - let moveY = 3; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = 1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("try to move double copied polyline down and to the right"); - cy.window().then(async (win) => { - let moveX = 1; - let moveY = -7; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g3/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = -1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolylineCopiedTwice({ vertices }); - }); - }); - - it("Two vertices constrained to same grid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,5) - - - - - (-4,-1) - (5,2) - - - - - (-3,4) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 4], - [-4, -1], - [6, 4], - [-3, 4], - ]; - - testPolylineCopiedTwice({ vertices }); - - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move copied polyline up and to the right"); - cy.window().then(async (win) => { - let moveX = 4; - let moveY = 3; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = 1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("try to move double copied polyline down and to the right"); - cy.window().then(async (win) => { - let moveX = 1; - let moveY = -7; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g3/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = -1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolylineCopiedTwice({ vertices }); - }); - }); - - it("Three vertices constrained to same grid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,5) - - - - - (-4,-1) - - - - - (5,2) - - - - - (-3,4) - - - - $(../g1/pg{name="pg"}) - - $g2{name="g3"} - $(g1/pg.vertices{assignNames="p1 p2 p3 p4"}) - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let vertices = [ - [3, 4], - [-3, 0], - [6, 4], - [-3, 4], - ]; - - testPolylineCopiedTwice({ vertices }); - - cy.log("move individual vertex"); - cy.window().then(async (win) => { - vertices[1] = [4, 7]; - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g1/pg", - args: { - pointCoords: { 1: vertices[1] }, - }, - }); - - // adjust for constraint - vertices[1] = [3, 8]; - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("move copied polyline up and to the right"); - cy.window().then(async (win) => { - let moveX = 4; - let moveY = 3; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g2/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = 1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolylineCopiedTwice({ vertices }); - }); - - cy.log("try to move double copied polyline down and to the right"); - cy.window().then(async (win) => { - let moveX = 1; - let moveY = -7; - - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - win.callAction1({ - actionName: "movePolyline", - componentName: "/g3/pg", - args: { - pointCoords: vertices, - }, - }); - - // adjustment due to constraint - moveX = -1; - moveY = -1; - for (let i = 0; i < vertices.length; i++) { - vertices[i][0] = vertices[i][0] + moveX; - vertices[i][1] = vertices[i][1] + moveY; - } - - testPolylineCopiedTwice({ vertices }); - }); - }); - - it("handle bad vertices", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // page loads - cy.get(cesc2("#/_text1")).should("have.text", "a"); - }); - - it("length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - -

length:

- `, - }, - "*", - ); - }); - - let length = 5 + 2 * Math.sqrt(2) + Math.sqrt(25 + 64); - - cy.get(cesc2("#/length")).should( - "have.text", - `${Math.round(length * 100) / 100}`, - ); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: { 1: [-8, -4] }, - }, - }); - win.callAction1({ - actionName: "movePolyline", - componentName: "/p", - args: { - pointCoords: { 2: [-8, 2] }, - }, - }); - - length = 13 + 6 + Math.sqrt(16 + 64) + Math.sqrt(25 + 64); - - cy.get(cesc2("#/length")).should( - "have.text", - `${Math.round(length * 100) / 100}`, - ); - }); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js deleted file mode 100644 index 05e8fd4a4..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js +++ /dev/null @@ -1,78 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("Single Character Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("dashes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 2 that's it - `, - }, - "*", - ); - }); - - // Note these dashes are different unicode even though they display the same here - cy.get(cesc("#\\/_document1")).should( - "contain.text", - "1 – 2 β€” that's it", - ); - }); - - it("nbsp", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - actlikeoneword - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_document1")).should( - "contain.text", - "act\u00a0like\u00a0one\u00a0word", - ); - }); - - it("ellipsis", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - we could do that - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_document1")).should( - "contain.text", - "we could do that…", - ); - }); - - it("unmatched quotes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_document1")).should("contain.text", "β€β€œβ€™β€˜"); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/text.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/text.cy.js index aa42fc3da..760074ed4 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/text.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/text.cy.js @@ -6,621 +6,6 @@ describe("Text Tag Tests", function () { cy.visit("/"); }); - it("spaces preserved between tags", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Hello there!

- -

We could be $_text2.

- `, - }, - "*", - ); - }); - - cy.get("p" + cesc("#\\/_p1")) - .invoke("text") - .should("contain", "Hello there!"); - cy.get("p" + cesc("#\\/_p2")) - .invoke("text") - .should("contain", "We could be there."); - }); - - it("components adapt to text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

boolean: true

-

number: 5-2

-

math: 5-2

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "true"); - cy.get(cesc("#\\/_text2")).should("have.text", "3"); - cy.get(cesc("#\\/_text3")).should("have.text", "5 - 2"); - }); - - it("text adapts to components", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

number: 4/2

-

number from latex: \\frac{4}{2}

-

number from latex 2: \\frac{4}{2}

-

number latex not parsed as latex: \\frac{4}{2}

-

number does not adapt with convertBoolean: 4/2

-

number multiplies adjacent texts: 54

-

number multiplies adjacent text and string: 54

-

math: sin(2x)

-

math from latex: \\sin(2x)

-

math from latex 2: \\sin(2x)

-

math latex not parsed as latex: \\sin(2x)

-

math multiplies adjacent texts: 54

-

math multiplies adjacent text and string: 54

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/n1")).should("have.text", "2"); - cy.get(cesc2("#/n2")).should("have.text", "2"); - cy.get(cesc2("#/n2a")).should("have.text", "2"); - cy.get(cesc2("#/n3")).should("have.text", "NaN"); - cy.get(cesc2("#/n4")).should("have.text", "NaN"); - cy.get(cesc2("#/n5")).should("have.text", "20"); - cy.get(cesc2("#/n6")).should("have.text", "20"); - cy.get(cesc2("#/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "sin(2x)"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "sin(2x)"); - cy.get(cesc2("#/m2a") + " .mjx-mrow") - .eq(0) - .should("have.text", "sin(2x)"); - cy.get(cesc2("#/m3") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "20"); - cy.get(cesc2("#/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "20"); - }); - - it("text from paragraph components", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Hello, said the cow. Bye, came the reply. The text attribute of text or text (or text?) doesn't do much.

- -

$orig.text{assignNames="t"}

- -

Hello, said the cow. Bye, came the reply. The text attribute of text or text (or text?) doesn't do much.

- `, - }, - "*", - ); - }); - - let theText = `"Hello," said the cow. 'Bye,' came the reply. The text attribute of or (or ?) doesn't do much.`; - - cy.get(cesc("#\\/orig")).should( - "have.text", - `β€œHello,” said the cow. β€˜Bye,’ came the reply. The text attribute of or (or ?) doesn't do much.`, - ); - cy.get(cesc("#\\/textOnly")).should("have.text", theText); - cy.get(cesc("#\\/insideText")).should("have.text", theText); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/t"].stateValues.value).eq(theText); - expect(stateVariables["/t2"].stateValues.value).eq(theText); - }); - }); - - it("text from single character components", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Pick a number from 1 2 no, maybe from3

- -

$orig.text{assignNames="t"}

- -

Pick a number from 1 2 no, maybe from3

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/orig")).should( - "have.text", - "Pick a β€˜number’ from 1 – 2 β€” no, β€œmaybe” from\u00a03…", - ); - cy.get(cesc("#\\/textOnly")).should( - "have.text", - "Pick a β€˜number’ from 1 – 2 β€” no, β€œmaybe” from\u00a03…", - ); - cy.get(cesc("#\\/insideText")).should( - "have.text", - "Pick a β€˜number’ from 1 – 2 β€” no, β€œmaybe” from\u00a03…", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/t"].stateValues.value).eq( - `Pick a β€˜number’ from 1 – 2 β€” no, β€œmaybe” from\u00a03…`, - ); - expect(stateVariables["/t2"].stateValues.value).eq( - `Pick a β€˜number’ from 1 – 2 β€” no, β€œmaybe” from\u00a03…`, - ); - }); - }); - - it("text does not force composite replacement, even in boolean", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $nothing = - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - }); - - it("text in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $content1 - bye - - -

Anchor 1 coordinates: $text1.anchor

-

Anchor 2 coordinates: $text2.anchor

-

Change anchor 1 coordinates:

-

Change anchor 2 coordinates:

-

Position from anchor 1: $text1.positionFromAnchor

-

Position from anchor 2: $text2.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

-

Content 1: $text1

-

Content 2: $text2

-

Content 1

-

Content 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

-

- - `, - }, - "*", - ); - }); - - 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.get(cesc("#\\/pContent1")).should("have.text", "Content 1: hello"); - cy.get(cesc("#\\/pContent2")).should("have.text", "Content 2: bye"); - - cy.log("move texts by dragging"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveText", - componentName: "/text1", - args: { x: -2, y: 3 }, - }); - win.callAction1({ - actionName: "moveText", - componentName: "/text2", - 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 texts 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 texts by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveText", - componentName: "/text1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveText", - componentName: "/text2", - 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("change content of text"); - cy.get(cesc("#\\/content1_input")).type("{end} there{enter}"); - cy.get(cesc("#\\/content2_input")).type("{end} now{enter}"); - - cy.get(cesc("#\\/pContent1")).should( - "have.text", - "Content 1: hello there", - ); - cy.get(cesc("#\\/pContent2")).should("have.text", "Content 2: bye now"); - - 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: "moveText", - componentName: "/text1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveText", - componentName: "/text2", - 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 text 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 texts by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveText", - componentName: "/text1", - args: { x: 4, y: 6 }, - }); - win.callAction1({ - actionName: "moveText", - componentName: "/text2", - 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 text 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("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 text 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 text 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 content only for text 1"); - cy.get(cesc("#\\/content2")).type("{end} too{enter}"); - cy.get(cesc("#\\/content1")).type("{end} again{enter}"); - cy.get(cesc("#\\/pContent1")).should( - "have.text", - "Content 1: hello there again", - ); - cy.get(cesc("#\\/pContent2")).should("have.text", "Content 2: bye now"); - }); - - it("text in graph, handle bad anchor coordinates", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - Hello - - - -

Anchor 1 coordinates: $text1.anchor

-

Change anchor 1 coordinates:

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.log("give good anchor coords"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(6,7){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(6,7)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - - cy.log("give bad anchor coords again"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}q{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should("contain.text", "q"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - }); - it("color text via style", () => { cy.window().then(async (win) => { win.postMessage( @@ -1009,24 +394,4 @@ describe("Text Tag Tests", function () { .should("have.text", "(βˆ’5,βˆ’4)"); }); }); - - it("numCharacters", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Hello there!

- -

Number of characters is $t.numCharacters.

- `, - }, - "*", - ); - }); - - cy.get("p" + cesc2("#/p2")).should( - "have.text", - "Number of characters is 11.", - ); - }); });