@doenet/doenetml 0.6.0-alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (549) hide show
  1. package/.prettierrc +3 -0
  2. package/LICENSE +661 -0
  3. package/README.md +146 -0
  4. package/cypress/e2e/ActivityViewer/activityVariants.cy.js +1770 -0
  5. package/cypress/e2e/ActivityViewer/compiledActivity.cy.js +83 -0
  6. package/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js +697 -0
  7. package/cypress/e2e/answerValidation/errorinnumbers.cy.js +2125 -0
  8. package/cypress/e2e/answerValidation/factoring.cy.js +1945 -0
  9. package/cypress/e2e/answerValidation/factoringOldAlgorithm.cy.js +892 -0
  10. package/cypress/e2e/answerValidation/functionanswers.cy.js +314 -0
  11. package/cypress/e2e/answerValidation/matchingpatterns.cy.js +287 -0
  12. package/cypress/e2e/answerValidation/matchpartial.cy.js +6711 -0
  13. package/cypress/e2e/answerValidation/pointlocation.cy.js +3989 -0
  14. package/cypress/e2e/answerValidation/symbolicequality.cy.js +1893 -0
  15. package/cypress/e2e/answerValidation/videoProgress.cy.js +210 -0
  16. package/cypress/e2e/assignNames/basiccopy.cy.js +2376 -0
  17. package/cypress/e2e/assignNames/collections.cy.js +9247 -0
  18. package/cypress/e2e/assignNames/selects.cy.js +105 -0
  19. package/cypress/e2e/assignNames/sequences.cy.js +1964 -0
  20. package/cypress/e2e/baseComponent/basecomponentproperties.cy.js +999 -0
  21. package/cypress/e2e/baseComponent/doenetMLtext.cy.js +427 -0
  22. package/cypress/e2e/chemistry/atom.cy.js +201 -0
  23. package/cypress/e2e/chemistry/ion.cy.js +608 -0
  24. package/cypress/e2e/chemistry/ioniccompound.cy.js +133 -0
  25. package/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +2653 -0
  26. package/cypress/e2e/dynamicalsystem/equilibriumcurve.cy.js +311 -0
  27. package/cypress/e2e/dynamicalsystem/equilibriumline.cy.js +279 -0
  28. package/cypress/e2e/dynamicalsystem/equilibriumpoint.cy.js +283 -0
  29. package/cypress/e2e/dynamicalsystem/odesystem.cy.js +1834 -0
  30. package/cypress/e2e/equality/mathexpressions.cy.js +948 -0
  31. package/cypress/e2e/graphing/graphreferences.cy.js +978 -0
  32. package/cypress/e2e/graphing/graphreferences2.cy.js +615 -0
  33. package/cypress/e2e/linearAlgebra/eigenDecomposition.cy.js +401 -0
  34. package/cypress/e2e/tagSpecific/angle.cy.js +3898 -0
  35. package/cypress/e2e/tagSpecific/animatefromsequence.cy.js +2306 -0
  36. package/cypress/e2e/tagSpecific/answer.cy.js +31647 -0
  37. package/cypress/e2e/tagSpecific/bestfitline.cy.js +612 -0
  38. package/cypress/e2e/tagSpecific/blockquote.cy.js +30 -0
  39. package/cypress/e2e/tagSpecific/boolean.cy.js +742 -0
  40. package/cypress/e2e/tagSpecific/booleaninput.cy.js +1283 -0
  41. package/cypress/e2e/tagSpecific/booleanlist.cy.js +588 -0
  42. package/cypress/e2e/tagSpecific/booleanoperators.cy.js +596 -0
  43. package/cypress/e2e/tagSpecific/booleanoperatorsonmath.cy.js +498 -0
  44. package/cypress/e2e/tagSpecific/callaction.cy.js +2835 -0
  45. package/cypress/e2e/tagSpecific/choiceinput.cy.js +3205 -0
  46. package/cypress/e2e/tagSpecific/circle.cy.js +22036 -0
  47. package/cypress/e2e/tagSpecific/codeeditor.cy.js +1995 -0
  48. package/cypress/e2e/tagSpecific/collect.cy.js +5035 -0
  49. package/cypress/e2e/tagSpecific/componentsize.cy.js +502 -0
  50. package/cypress/e2e/tagSpecific/conditionalcontent.cy.js +3495 -0
  51. package/cypress/e2e/tagSpecific/contentBrowser.cy.js +335 -0
  52. package/cypress/e2e/tagSpecific/contentpicker.cy.js +261 -0
  53. package/cypress/e2e/tagSpecific/copy.cy.js +12627 -0
  54. package/cypress/e2e/tagSpecific/copy2.cy.js +5698 -0
  55. package/cypress/e2e/tagSpecific/curve.bezier.cy.js +12440 -0
  56. package/cypress/e2e/tagSpecific/curve.cy.js +1716 -0
  57. package/cypress/e2e/tagSpecific/curve.function.cy.js +1471 -0
  58. package/cypress/e2e/tagSpecific/curve.parametrized.cy.js +920 -0
  59. package/cypress/e2e/tagSpecific/document.cy.js +234 -0
  60. package/cypress/e2e/tagSpecific/endpoint.cy.js +197 -0
  61. package/cypress/e2e/tagSpecific/evaluate.cy.js +8895 -0
  62. package/cypress/e2e/tagSpecific/extract.cy.js +2282 -0
  63. package/cypress/e2e/tagSpecific/feedback.cy.js +2941 -0
  64. package/cypress/e2e/tagSpecific/function.cy.js +9450 -0
  65. package/cypress/e2e/tagSpecific/functioniterates.cy.js +1178 -0
  66. package/cypress/e2e/tagSpecific/functionoperators.cy.js +4047 -0
  67. package/cypress/e2e/tagSpecific/graph.cy.js +2491 -0
  68. package/cypress/e2e/tagSpecific/group.cy.js +683 -0
  69. package/cypress/e2e/tagSpecific/hint.cy.js +204 -0
  70. package/cypress/e2e/tagSpecific/image.cy.js +770 -0
  71. package/cypress/e2e/tagSpecific/integer.cy.js +206 -0
  72. package/cypress/e2e/tagSpecific/label.cy.js +800 -0
  73. package/cypress/e2e/tagSpecific/legend.cy.js +1001 -0
  74. package/cypress/e2e/tagSpecific/line.cy.js +12167 -0
  75. package/cypress/e2e/tagSpecific/linesegment.cy.js +4749 -0
  76. package/cypress/e2e/tagSpecific/lorem.cy.js +289 -0
  77. package/cypress/e2e/tagSpecific/map.cy.js +4476 -0
  78. package/cypress/e2e/tagSpecific/matchespattern.cy.js +693 -0
  79. package/cypress/e2e/tagSpecific/math.cy.js +10990 -0
  80. package/cypress/e2e/tagSpecific/mathdisplay.cy.js +2689 -0
  81. package/cypress/e2e/tagSpecific/mathinput.cy.js +15628 -0
  82. package/cypress/e2e/tagSpecific/mathinputgraph.cy.js +566 -0
  83. package/cypress/e2e/tagSpecific/mathlist.cy.js +4073 -0
  84. package/cypress/e2e/tagSpecific/mathoperators.cy.js +13851 -0
  85. package/cypress/e2e/tagSpecific/matrix.cy.js +8825 -0
  86. package/cypress/e2e/tagSpecific/matrixinput.cy.js +16277 -0
  87. package/cypress/e2e/tagSpecific/module.cy.js +1771 -0
  88. package/cypress/e2e/tagSpecific/number.cy.js +2221 -0
  89. package/cypress/e2e/tagSpecific/numberlist.cy.js +1285 -0
  90. package/cypress/e2e/tagSpecific/p.cy.js +72 -0
  91. package/cypress/e2e/tagSpecific/paginator.cy.js +2983 -0
  92. package/cypress/e2e/tagSpecific/parabola.cy.js +14331 -0
  93. package/cypress/e2e/tagSpecific/paragraphmarkup.cy.js +104 -0
  94. package/cypress/e2e/tagSpecific/periodicset.cy.js +1439 -0
  95. package/cypress/e2e/tagSpecific/piecewisefunction.cy.js +1055 -0
  96. package/cypress/e2e/tagSpecific/pluralize.cy.js +274 -0
  97. package/cypress/e2e/tagSpecific/point.cy.js +8895 -0
  98. package/cypress/e2e/tagSpecific/point2.cy.js +10259 -0
  99. package/cypress/e2e/tagSpecific/polygon.cy.js +5039 -0
  100. package/cypress/e2e/tagSpecific/polyline.cy.js +4704 -0
  101. package/cypress/e2e/tagSpecific/problem.cy.js +2768 -0
  102. package/cypress/e2e/tagSpecific/ray.cy.js +10770 -0
  103. package/cypress/e2e/tagSpecific/rectangle.cy.js +2143 -0
  104. package/cypress/e2e/tagSpecific/ref.cy.js +420 -0
  105. package/cypress/e2e/tagSpecific/regularPolygon.cy.js +1006 -0
  106. package/cypress/e2e/tagSpecific/regularPolygon2.cy.js +100 -0
  107. package/cypress/e2e/tagSpecific/regularPolygon3.cy.js +777 -0
  108. package/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js +3619 -0
  109. package/cypress/e2e/tagSpecific/sectioning.cy.js +3530 -0
  110. package/cypress/e2e/tagSpecific/select.cy.js +5376 -0
  111. package/cypress/e2e/tagSpecific/selectfromsequence.cy.js +3846 -0
  112. package/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js +2914 -0
  113. package/cypress/e2e/tagSpecific/sequence.cy.js +2093 -0
  114. package/cypress/e2e/tagSpecific/shuffle.cy.js +490 -0
  115. package/cypress/e2e/tagSpecific/sidebyside.cy.js +8057 -0
  116. package/cypress/e2e/tagSpecific/singlecharactercomponents.cy.js +72 -0
  117. package/cypress/e2e/tagSpecific/slider.cy.js +914 -0
  118. package/cypress/e2e/tagSpecific/solution.cy.js +109 -0
  119. package/cypress/e2e/tagSpecific/solveequations.cy.js +1026 -0
  120. package/cypress/e2e/tagSpecific/sort.cy.js +1685 -0
  121. package/cypress/e2e/tagSpecific/spreadsheet.cy.js +5971 -0
  122. package/cypress/e2e/tagSpecific/subsetofreals.cy.js +2725 -0
  123. package/cypress/e2e/tagSpecific/substitute.cy.js +2646 -0
  124. package/cypress/e2e/tagSpecific/tabular.cy.js +36 -0
  125. package/cypress/e2e/tagSpecific/text.cy.js +975 -0
  126. package/cypress/e2e/tagSpecific/textinput.cy.js +2177 -0
  127. package/cypress/e2e/tagSpecific/textlist.cy.js +369 -0
  128. package/cypress/e2e/tagSpecific/triangle.cy.js +1936 -0
  129. package/cypress/e2e/tagSpecific/triggerset.cy.js +2023 -0
  130. package/cypress/e2e/tagSpecific/updatevalue.cy.js +3288 -0
  131. package/cypress/e2e/tagSpecific/vector.cy.js +20183 -0
  132. package/cypress/e2e/tagSpecific/video.cy.js +612 -0
  133. package/cypress/e2e/tagSpecific/when.cy.js +202 -0
  134. package/cypress/e2e/variants/specifysinglevariant.cy.js +6726 -0
  135. package/cypress/e2e/variants/uniquevariants.cy.js +4846 -0
  136. package/cypress/fixtures/example.json +5 -0
  137. package/cypress/support/commands.js +32 -0
  138. package/cypress/support/e2e.js +31 -0
  139. package/cypress.config.js +18 -0
  140. package/docs/codeSnippet.jsx +11 -0
  141. package/docs/index.html +133 -0
  142. package/docs/index.jsx +138 -0
  143. package/docs/prism.css +3 -0
  144. package/index.html +14 -0
  145. package/index.js +21 -0
  146. package/media/answer_example.png +0 -0
  147. package/media/graph_example.png +0 -0
  148. package/media/graph_markup_example.png +0 -0
  149. package/package.json +83 -0
  150. package/public/favicon.ico +0 -0
  151. package/public/fonts/files/open-sans-v18-latin-700.woff +0 -0
  152. package/public/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
  153. package/public/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
  154. package/public/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
  155. package/public/fonts/files/open-sans-v18-latin-italic.woff +0 -0
  156. package/public/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
  157. package/public/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
  158. package/public/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
  159. package/public/fonts/files/open-sans-v18-latin-light.woff +0 -0
  160. package/public/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
  161. package/public/fonts/files/open-sans-v18-latin-regular.woff +0 -0
  162. package/public/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
  163. package/src/Core/ComponentTypes.js +426 -0
  164. package/src/Core/Core.js +11852 -0
  165. package/src/Core/CoreWorker.js +127 -0
  166. package/src/Core/Dependencies.js +8226 -0
  167. package/src/Core/Numerics.js +473 -0
  168. package/src/Core/ParameterStack.js +36 -0
  169. package/src/Core/ReadOnlyProxyHandler.js +41 -0
  170. package/src/Core/StateProxyHandler.js +88 -0
  171. package/src/Core/components/Aliases.js +67 -0
  172. package/src/Core/components/Angle.js +758 -0
  173. package/src/Core/components/AnimateFromSequence.js +922 -0
  174. package/src/Core/components/Answer.js +2087 -0
  175. package/src/Core/components/AsList.js +83 -0
  176. package/src/Core/components/AttractTo.js +245 -0
  177. package/src/Core/components/AttractToAngles.js +262 -0
  178. package/src/Core/components/AttractToConstraint.js +104 -0
  179. package/src/Core/components/AttractToGrid.js +315 -0
  180. package/src/Core/components/Award.js +906 -0
  181. package/src/Core/components/BestFitLine.js +318 -0
  182. package/src/Core/components/BezierControls.js +719 -0
  183. package/src/Core/components/BlockQuote.js +35 -0
  184. package/src/Core/components/Boolean.js +500 -0
  185. package/src/Core/components/BooleanInput.js +330 -0
  186. package/src/Core/components/BooleanList.js +396 -0
  187. package/src/Core/components/BooleanOperators.js +35 -0
  188. package/src/Core/components/BooleanOperatorsOfMath.js +148 -0
  189. package/src/Core/components/CallAction.js +261 -0
  190. package/src/Core/components/Caption.js +73 -0
  191. package/src/Core/components/Case.js +56 -0
  192. package/src/Core/components/Cell.js +439 -0
  193. package/src/Core/components/CellBlock.js +64 -0
  194. package/src/Core/components/Chart.js +795 -0
  195. package/src/Core/components/Choice.js +266 -0
  196. package/src/Core/components/ChoiceInput.js +1407 -0
  197. package/src/Core/components/Circle.js +2884 -0
  198. package/src/Core/components/CodeEditor.js +647 -0
  199. package/src/Core/components/CodeViewer.js +294 -0
  200. package/src/Core/components/CollaborateGroupSetup.js +46 -0
  201. package/src/Core/components/CollaborateGroups.js +119 -0
  202. package/src/Core/components/Collect.js +850 -0
  203. package/src/Core/components/Column.js +608 -0
  204. package/src/Core/components/ConditionalContent.js +468 -0
  205. package/src/Core/components/ConsiderAsResponses.js +49 -0
  206. package/src/Core/components/ConstrainTo.js +161 -0
  207. package/src/Core/components/ConstrainToAngles.js +244 -0
  208. package/src/Core/components/ConstrainToGraph.js +142 -0
  209. package/src/Core/components/ConstrainToGrid.js +175 -0
  210. package/src/Core/components/ConstraintUnion.js +119 -0
  211. package/src/Core/components/Constraints.js +497 -0
  212. package/src/Core/components/ContentBrowser.js +441 -0
  213. package/src/Core/components/ContentPicker.js +263 -0
  214. package/src/Core/components/ControlVectors.js +25 -0
  215. package/src/Core/components/Coords.js +63 -0
  216. package/src/Core/components/Copy.js +3412 -0
  217. package/src/Core/components/Curve.js +4130 -0
  218. package/src/Core/components/CustomAttribute.js +175 -0
  219. package/src/Core/components/DataFrame.js +357 -0
  220. package/src/Core/components/DiscreteSimulationResultList.js +342 -0
  221. package/src/Core/components/DiscreteSimulationResultPolyline.js +581 -0
  222. package/src/Core/components/Divisions.js +55 -0
  223. package/src/Core/components/Document.js +888 -0
  224. package/src/Core/components/Embed.js +65 -0
  225. package/src/Core/components/Endpoint.js +62 -0
  226. package/src/Core/components/Evaluate.js +321 -0
  227. package/src/Core/components/Extract.js +656 -0
  228. package/src/Core/components/Extrema.js +556 -0
  229. package/src/Core/components/Feedback.js +200 -0
  230. package/src/Core/components/FeedbackDefinitions.js +97 -0
  231. package/src/Core/components/Figure.js +148 -0
  232. package/src/Core/components/Footnote.js +73 -0
  233. package/src/Core/components/Function.js +5344 -0
  234. package/src/Core/components/FunctionIterates.js +306 -0
  235. package/src/Core/components/FunctionOperators.js +702 -0
  236. package/src/Core/components/Graph.js +1679 -0
  237. package/src/Core/components/Group.js +7 -0
  238. package/src/Core/components/HasSameFactoring.js +407 -0
  239. package/src/Core/components/Hint.js +241 -0
  240. package/src/Core/components/Image.js +524 -0
  241. package/src/Core/components/Indexing.js +79 -0
  242. package/src/Core/components/IntComma.js +64 -0
  243. package/src/Core/components/Integer.js +81 -0
  244. package/src/Core/components/Intersection.js +328 -0
  245. package/src/Core/components/Interval.js +29 -0
  246. package/src/Core/components/Label.js +492 -0
  247. package/src/Core/components/Latex.js +104 -0
  248. package/src/Core/components/Legend.js +329 -0
  249. package/src/Core/components/Line.js +2040 -0
  250. package/src/Core/components/LineSegment.js +882 -0
  251. package/src/Core/components/Lists.js +180 -0
  252. package/src/Core/components/Lorem.js +249 -0
  253. package/src/Core/components/MMeMen.js +377 -0
  254. package/src/Core/components/Map.js +873 -0
  255. package/src/Core/components/Markers.js +101 -0
  256. package/src/Core/components/MatchesPattern.js +339 -0
  257. package/src/Core/components/Math.js +2552 -0
  258. package/src/Core/components/MathInput.js +948 -0
  259. package/src/Core/components/MathList.js +828 -0
  260. package/src/Core/components/MathOperators.js +1286 -0
  261. package/src/Core/components/Matrix.js +497 -0
  262. package/src/Core/components/MatrixInput.js +3157 -0
  263. package/src/Core/components/MdMdnMrow.js +394 -0
  264. package/src/Core/components/Module.js +16 -0
  265. package/src/Core/components/Number.js +1031 -0
  266. package/src/Core/components/NumberList.js +550 -0
  267. package/src/Core/components/Option.js +24 -0
  268. package/src/Core/components/P.js +71 -0
  269. package/src/Core/components/Paginator.js +338 -0
  270. package/src/Core/components/Panel.js +126 -0
  271. package/src/Core/components/Parabola.js +1561 -0
  272. package/src/Core/components/ParagraphMarkup.js +59 -0
  273. package/src/Core/components/Pegboard.js +43 -0
  274. package/src/Core/components/PeriodicSet.js +291 -0
  275. package/src/Core/components/PiecewiseFunction.js +832 -0
  276. package/src/Core/components/Pluralize.js +198 -0
  277. package/src/Core/components/Point.js +1295 -0
  278. package/src/Core/components/Polygon.js +408 -0
  279. package/src/Core/components/Polyline.js +841 -0
  280. package/src/Core/components/RandomizedTextList.js +225 -0
  281. package/src/Core/components/Ray.js +1737 -0
  282. package/src/Core/components/Rectangle.js +1535 -0
  283. package/src/Core/components/Ref.js +350 -0
  284. package/src/Core/components/RegionBetweenCurveXAxis.js +124 -0
  285. package/src/Core/components/RegionHalfPlane.js +107 -0
  286. package/src/Core/components/RegularPolygon.js +2118 -0
  287. package/src/Core/components/RenderDoenetML.js +181 -0
  288. package/src/Core/components/Row.js +780 -0
  289. package/src/Core/components/SampleRandomNumbers.js +653 -0
  290. package/src/Core/components/Sectioning.js +303 -0
  291. package/src/Core/components/Select.js +947 -0
  292. package/src/Core/components/SelectFromSequence.js +1242 -0
  293. package/src/Core/components/SelectRandomNumbers.js +225 -0
  294. package/src/Core/components/Sequence.js +444 -0
  295. package/src/Core/components/Setup.js +53 -0
  296. package/src/Core/components/Shuffle.js +470 -0
  297. package/src/Core/components/SideBySide.js +2130 -0
  298. package/src/Core/components/SingleCharacterComponents.js +41 -0
  299. package/src/Core/components/Slider.js +819 -0
  300. package/src/Core/components/SolutionContainer.js +67 -0
  301. package/src/Core/components/Solutions.js +334 -0
  302. package/src/Core/components/SolveEquations.js +568 -0
  303. package/src/Core/components/Sort.js +398 -0
  304. package/src/Core/components/Sources.js +108 -0
  305. package/src/Core/components/Split.js +205 -0
  306. package/src/Core/components/Spreadsheet.js +1507 -0
  307. package/src/Core/components/StyleDefinitions.js +111 -0
  308. package/src/Core/components/SubsetOfReals.js +348 -0
  309. package/src/Core/components/SubsetOfRealsInput.js +1474 -0
  310. package/src/Core/components/Substitute.js +496 -0
  311. package/src/Core/components/SummaryStatistics.js +652 -0
  312. package/src/Core/components/Table.js +145 -0
  313. package/src/Core/components/Tabular.js +384 -0
  314. package/src/Core/components/Template.js +360 -0
  315. package/src/Core/components/Text.js +341 -0
  316. package/src/Core/components/TextInput.js +566 -0
  317. package/src/Core/components/TextList.js +442 -0
  318. package/src/Core/components/TextListFromString.js +137 -0
  319. package/src/Core/components/TextOperatorsOfMath.js +21 -0
  320. package/src/Core/components/Triangle.js +280 -0
  321. package/src/Core/components/TriggerSet.js +189 -0
  322. package/src/Core/components/TupleList.js +43 -0
  323. package/src/Core/components/UpdateValue.js +435 -0
  324. package/src/Core/components/VariantControl.js +36 -0
  325. package/src/Core/components/Vector.js +2478 -0
  326. package/src/Core/components/Verbatim.js +125 -0
  327. package/src/Core/components/Video.js +673 -0
  328. package/src/Core/components/When.js +198 -0
  329. package/src/Core/components/abstract/AngleListComponent.js +140 -0
  330. package/src/Core/components/abstract/BaseComponent.js +1496 -0
  331. package/src/Core/components/abstract/BlockComponent.js +5 -0
  332. package/src/Core/components/abstract/BooleanBaseOperator.js +88 -0
  333. package/src/Core/components/abstract/BooleanBaseOperatorOfMath.js +100 -0
  334. package/src/Core/components/abstract/BooleanBaseOperatorOneInput.js +44 -0
  335. package/src/Core/components/abstract/ComponentSize.js +789 -0
  336. package/src/Core/components/abstract/ComponentWithSelectableType.js +537 -0
  337. package/src/Core/components/abstract/CompositeComponent.js +142 -0
  338. package/src/Core/components/abstract/ConstraintComponent.js +19 -0
  339. package/src/Core/components/abstract/FunctionBaseOperator.js +680 -0
  340. package/src/Core/components/abstract/GraphicalComponent.js +56 -0
  341. package/src/Core/components/abstract/InlineComponent.js +5 -0
  342. package/src/Core/components/abstract/InlineRenderInlineChildren.js +63 -0
  343. package/src/Core/components/abstract/Input.js +192 -0
  344. package/src/Core/components/abstract/IntervalListComponent.js +218 -0
  345. package/src/Core/components/abstract/LineListComponent.js +114 -0
  346. package/src/Core/components/abstract/MathBaseOperator.js +631 -0
  347. package/src/Core/components/abstract/MathBaseOperatorOneInput.js +112 -0
  348. package/src/Core/components/abstract/PointListComponent.js +238 -0
  349. package/src/Core/components/abstract/SectioningComponent.js +1262 -0
  350. package/src/Core/components/abstract/SingleCharacterInline.js +23 -0
  351. package/src/Core/components/abstract/TextBaseOperatorOfMath.js +47 -0
  352. package/src/Core/components/abstract/TextOrInline.js +66 -0
  353. package/src/Core/components/abstract/VariableName.js +31 -0
  354. package/src/Core/components/abstract/VariableNameList.js +83 -0
  355. package/src/Core/components/abstract/VectorListComponent.js +235 -0
  356. package/src/Core/components/chemistry/Atom.js +910 -0
  357. package/src/Core/components/chemistry/ElectronConfiguration.js +36 -0
  358. package/src/Core/components/chemistry/Ion.js +684 -0
  359. package/src/Core/components/chemistry/IonicCompound.js +189 -0
  360. package/src/Core/components/chemistry/OrbitalDiagram.js +175 -0
  361. package/src/Core/components/chemistry/OrbitalDiagramInput.js +753 -0
  362. package/src/Core/components/chemistry/index.js +6 -0
  363. package/src/Core/components/commonsugar/breakstrings.js +627 -0
  364. package/src/Core/components/commonsugar/lists.js +177 -0
  365. package/src/Core/components/dynamicalSystems/CobwebPolyline.js +913 -0
  366. package/src/Core/components/dynamicalSystems/EquilibriumCurve.js +95 -0
  367. package/src/Core/components/dynamicalSystems/EquilibriumLine.js +93 -0
  368. package/src/Core/components/dynamicalSystems/EquilibriumPoint.js +93 -0
  369. package/src/Core/components/dynamicalSystems/ODESystem.js +943 -0
  370. package/src/Core/components/dynamicalSystems/index.js +5 -0
  371. package/src/Core/components/linearAlgebra/EigenDecomposition.js +294 -0
  372. package/src/Core/utils/array.js +30 -0
  373. package/src/Core/utils/booleanLogic.js +965 -0
  374. package/src/Core/utils/checkEquality.js +818 -0
  375. package/src/Core/utils/cid.js +29 -0
  376. package/src/Core/utils/componentInfoObjects.js +100 -0
  377. package/src/Core/utils/constraints.js +23 -0
  378. package/src/Core/utils/copy.js +572 -0
  379. package/src/Core/utils/deepFunctions.js +173 -0
  380. package/src/Core/utils/descendants.js +252 -0
  381. package/src/Core/utils/enumeration.js +234 -0
  382. package/src/Core/utils/feedback.js +84 -0
  383. package/src/Core/utils/function.js +1343 -0
  384. package/src/Core/utils/graphical.js +196 -0
  385. package/src/Core/utils/label.js +396 -0
  386. package/src/Core/utils/math.js +1056 -0
  387. package/src/Core/utils/naming.js +45 -0
  388. package/src/Core/utils/periodicSetEquality.js +403 -0
  389. package/src/Core/utils/randomNumbers.js +70 -0
  390. package/src/Core/utils/retrieveMedia.js +98 -0
  391. package/src/Core/utils/retrieveTextFile.js +140 -0
  392. package/src/Core/utils/returnAllPossibleVariants.js +73 -0
  393. package/src/Core/utils/rounding.js +316 -0
  394. package/src/Core/utils/sequence.js +754 -0
  395. package/src/Core/utils/serializedStateProcessing.js +4049 -0
  396. package/src/Core/utils/size.js +22 -0
  397. package/src/Core/utils/stateVariables.js +138 -0
  398. package/src/Core/utils/style.js +535 -0
  399. package/src/Core/utils/subset-of-reals.js +796 -0
  400. package/src/Core/utils/table.js +41 -0
  401. package/src/Core/utils/text.js +16 -0
  402. package/src/Core/utils/triggering.js +167 -0
  403. package/src/Core/utils/variants.js +477 -0
  404. package/src/DoenetML.css +308 -0
  405. package/src/DoenetML.jsx +201 -0
  406. package/src/Parser/doenet.grammar +90 -0
  407. package/src/Parser/doenet.js +33 -0
  408. package/src/Parser/doenet.terms.js +20 -0
  409. package/src/Parser/parser.js +266 -0
  410. package/src/Parser/tokens.js +129 -0
  411. package/src/Tools/CodeMirror.jsx +440 -0
  412. package/src/Tools/DarkmodeController.jsx +21 -0
  413. package/src/Tools/Footers/MathInputSelector.jsx +34 -0
  414. package/src/Tools/Footers/VirtualKeyboard.jsx +751 -0
  415. package/src/Tools/cypressTest/CypressTest.jsx +341 -0
  416. package/src/Tools/cypressTest/index.html +102 -0
  417. package/src/Tools/cypressTest/index.jsx +40 -0
  418. package/src/Viewer/ActivityViewer.jsx +1461 -0
  419. package/src/Viewer/PageViewer.jsx +1329 -0
  420. package/src/Viewer/renderers/alert.jsx +17 -0
  421. package/src/Viewer/renderers/angle.jsx +209 -0
  422. package/src/Viewer/renderers/answer.jsx +206 -0
  423. package/src/Viewer/renderers/asList.jsx +25 -0
  424. package/src/Viewer/renderers/blockQuote.jsx +41 -0
  425. package/src/Viewer/renderers/boolean.jsx +17 -0
  426. package/src/Viewer/renderers/booleanInput.css +105 -0
  427. package/src/Viewer/renderers/booleanInput.jsx +636 -0
  428. package/src/Viewer/renderers/button.jsx +369 -0
  429. package/src/Viewer/renderers/c.jsx +17 -0
  430. package/src/Viewer/renderers/callAction.jsx +18 -0
  431. package/src/Viewer/renderers/cell.jsx +59 -0
  432. package/src/Viewer/renderers/chart.jsx +83 -0
  433. package/src/Viewer/renderers/choiceInput.css +223 -0
  434. package/src/Viewer/renderers/choiceInput.jsx +535 -0
  435. package/src/Viewer/renderers/circle.jsx +990 -0
  436. package/src/Viewer/renderers/cobwebPolyline.jsx +442 -0
  437. package/src/Viewer/renderers/codeEditor.jsx +248 -0
  438. package/src/Viewer/renderers/codeViewer.jsx +105 -0
  439. package/src/Viewer/renderers/containerBlock.jsx +41 -0
  440. package/src/Viewer/renderers/containerInline.jsx +17 -0
  441. package/src/Viewer/renderers/contentBrowser.jsx +159 -0
  442. package/src/Viewer/renderers/contentPicker.jsx +160 -0
  443. package/src/Viewer/renderers/curve.jsx +1072 -0
  444. package/src/Viewer/renderers/ellipsis.jsx +17 -0
  445. package/src/Viewer/renderers/em.jsx +17 -0
  446. package/src/Viewer/renderers/embed.jsx +110 -0
  447. package/src/Viewer/renderers/feedback.jsx +74 -0
  448. package/src/Viewer/renderers/figure.jsx +131 -0
  449. package/src/Viewer/renderers/footnote.jsx +52 -0
  450. package/src/Viewer/renderers/graph.jsx +925 -0
  451. package/src/Viewer/renderers/hint.jsx +142 -0
  452. package/src/Viewer/renderers/image.jsx +581 -0
  453. package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs +2 -0
  454. package/src/Viewer/renderers/jsxgraph-distrib/jsxgraphcore.mjs.map +1 -0
  455. package/src/Viewer/renderers/label.jsx +470 -0
  456. package/src/Viewer/renderers/legend.jsx +306 -0
  457. package/src/Viewer/renderers/line.jsx +511 -0
  458. package/src/Viewer/renderers/lineSegment.jsx +754 -0
  459. package/src/Viewer/renderers/list.jsx +111 -0
  460. package/src/Viewer/renderers/lq.jsx +12 -0
  461. package/src/Viewer/renderers/lsq.jsx +12 -0
  462. package/src/Viewer/renderers/math.jsx +582 -0
  463. package/src/Viewer/renderers/mathInput.css +10 -0
  464. package/src/Viewer/renderers/mathInput.jsx +425 -0
  465. package/src/Viewer/renderers/mathInputog.jsx +534 -0
  466. package/src/Viewer/renderers/mathList.jsx +39 -0
  467. package/src/Viewer/renderers/matrixInput.jsx +317 -0
  468. package/src/Viewer/renderers/mdash.jsx +12 -0
  469. package/src/Viewer/renderers/nbsp.jsx +12 -0
  470. package/src/Viewer/renderers/ndash.jsx +12 -0
  471. package/src/Viewer/renderers/number.jsx +454 -0
  472. package/src/Viewer/renderers/numberList.jsx +35 -0
  473. package/src/Viewer/renderers/orbitalDiagram.jsx +247 -0
  474. package/src/Viewer/renderers/orbitalDiagramInput.jsx +450 -0
  475. package/src/Viewer/renderers/p.jsx +38 -0
  476. package/src/Viewer/renderers/paginatorControls.jsx +41 -0
  477. package/src/Viewer/renderers/pegboard.jsx +239 -0
  478. package/src/Viewer/renderers/point.jsx +649 -0
  479. package/src/Viewer/renderers/polygon.jsx +612 -0
  480. package/src/Viewer/renderers/polyline.jsx +608 -0
  481. package/src/Viewer/renderers/pre.jsx +34 -0
  482. package/src/Viewer/renderers/q.jsx +17 -0
  483. package/src/Viewer/renderers/ray.jsx +410 -0
  484. package/src/Viewer/renderers/ref.jsx +149 -0
  485. package/src/Viewer/renderers/regionBetweenCurveXAxis.jsx +182 -0
  486. package/src/Viewer/renderers/renderDoenetML.jsx +56 -0
  487. package/src/Viewer/renderers/row.jsx +31 -0
  488. package/src/Viewer/renderers/rq.jsx +12 -0
  489. package/src/Viewer/renderers/rsq.jsx +12 -0
  490. package/src/Viewer/renderers/section.jsx +427 -0
  491. package/src/Viewer/renderers/sideBySide.jsx +80 -0
  492. package/src/Viewer/renderers/slider.jsx +800 -0
  493. package/src/Viewer/renderers/solution.jsx +134 -0
  494. package/src/Viewer/renderers/spreadsheet.jsx +83 -0
  495. package/src/Viewer/renderers/sq.jsx +17 -0
  496. package/src/Viewer/renderers/styles/global.css +14 -0
  497. package/src/Viewer/renderers/subsetOfRealsInput.jsx +392 -0
  498. package/src/Viewer/renderers/summaryStatistics.jsx +83 -0
  499. package/src/Viewer/renderers/table.jsx +78 -0
  500. package/src/Viewer/renderers/tabular.jsx +58 -0
  501. package/src/Viewer/renderers/tag.jsx +26 -0
  502. package/src/Viewer/renderers/text.jsx +439 -0
  503. package/src/Viewer/renderers/textInput.jsx +774 -0
  504. package/src/Viewer/renderers/textList.jsx +30 -0
  505. package/src/Viewer/renderers/triggerSet.jsx +52 -0
  506. package/src/Viewer/renderers/updateValue.jsx +30 -0
  507. package/src/Viewer/renderers/utils/css.js +13 -0
  508. package/src/Viewer/renderers/utils/graph.js +159 -0
  509. package/src/Viewer/renderers/utils/offGraphIndicators.js +91 -0
  510. package/src/Viewer/renderers/vector.jsx +678 -0
  511. package/src/Viewer/renderers/video.jsx +494 -0
  512. package/src/Viewer/useDoenetRenderer.jsx +128 -0
  513. package/src/main.jsx +16 -0
  514. package/src/media/fonts/files/open-sans-v18-latin-700.woff +0 -0
  515. package/src/media/fonts/files/open-sans-v18-latin-700.woff2 +0 -0
  516. package/src/media/fonts/files/open-sans-v18-latin-700italic.woff +0 -0
  517. package/src/media/fonts/files/open-sans-v18-latin-700italic.woff2 +0 -0
  518. package/src/media/fonts/files/open-sans-v18-latin-italic.woff +0 -0
  519. package/src/media/fonts/files/open-sans-v18-latin-italic.woff2 +0 -0
  520. package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff +0 -0
  521. package/src/media/fonts/files/open-sans-v18-latin-light-italic.woff2 +0 -0
  522. package/src/media/fonts/files/open-sans-v18-latin-light.woff +0 -0
  523. package/src/media/fonts/files/open-sans-v18-latin-light.woff2 +0 -0
  524. package/src/media/fonts/files/open-sans-v18-latin-regular.woff +0 -0
  525. package/src/media/fonts/files/open-sans-v18-latin-regular.woff2 +0 -0
  526. package/src/test/testCode.doenet +26 -0
  527. package/src/test/testViewer.jsx +158 -0
  528. package/src/uiComponents/ActionButton.jsx +157 -0
  529. package/src/uiComponents/ActionButtonGroup.jsx +93 -0
  530. package/src/uiComponents/Button.jsx +160 -0
  531. package/src/uiComponents/ButtonGroup.jsx +56 -0
  532. package/src/uiComponents/ToggleButton.jsx +194 -0
  533. package/src/uiComponents/ToggleButtonGroup.jsx +77 -0
  534. package/src/utils/activityUtils.js +713 -0
  535. package/src/utils/array.js +17 -0
  536. package/src/utils/cid.js +34 -0
  537. package/src/utils/componentInfoObjects.js +89 -0
  538. package/src/utils/deepFunctions.js +165 -0
  539. package/src/utils/enumeration.js +226 -0
  540. package/src/utils/math.js +624 -0
  541. package/src/utils/naming.js +44 -0
  542. package/src/utils/retrieveTextFile.js +156 -0
  543. package/src/utils/returnAllPossibleVariants.js +81 -0
  544. package/src/utils/sequence.js +715 -0
  545. package/src/utils/serialize.js +29 -0
  546. package/src/utils/serializedStateProcessing.js +2587 -0
  547. package/src/utils/subset-of-reals.js +783 -0
  548. package/src/utils/url.js +19 -0
  549. package/vite.config.js +14 -0
@@ -0,0 +1,2646 @@
1
+ import me from "math-expressions";
2
+ import { cesc } from "../../../../src/utils/url";
3
+
4
+ describe("Substitute Tag Tests", function () {
5
+ beforeEach(() => {
6
+ cy.clearIndexedDB();
7
+ cy.visit("/src/Tools/cypressTest/");
8
+ });
9
+
10
+ it("substitute into string sugared to math", () => {
11
+ cy.window().then(async (win) => {
12
+ win.postMessage(
13
+ {
14
+ doenetML: `
15
+ <text>a</text>
16
+ <substitute name="s_one" match="x" replacement="b" assignNames="one">
17
+ alpha+x^2
18
+ </substitute>
19
+ <substitute name="s_two" match="x" replacement="b" assignNames="two">
20
+ <substitute match="alpha" replacement="d">
21
+ alpha+x^2
22
+ </substitute>
23
+ </substitute>
24
+ `,
25
+ },
26
+ "*",
27
+ );
28
+ });
29
+
30
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
31
+
32
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
33
+ .eq(0)
34
+ .invoke("text")
35
+ .then((text) => {
36
+ expect(text.trim()).equal("α+b2");
37
+ });
38
+ cy.get(cesc("#\\/two") + " .mjx-mrow")
39
+ .eq(0)
40
+ .invoke("text")
41
+ .then((text) => {
42
+ expect(text.trim()).equal("d+b2");
43
+ });
44
+
45
+ cy.window().then(async (win) => {
46
+ let stateVariables = await win.returnAllStateVariables1();
47
+ expect(stateVariables["/s_one"].stateValues.value).eqls([
48
+ "+",
49
+ "alpha",
50
+ ["^", "b", 2],
51
+ ]);
52
+ expect(stateVariables["/one"].stateValues.value).eqls([
53
+ "+",
54
+ "alpha",
55
+ ["^", "b", 2],
56
+ ]);
57
+ expect(stateVariables["/s_two"].stateValues.value).eqls([
58
+ "+",
59
+ "d",
60
+ ["^", "b", 2],
61
+ ]);
62
+ expect(stateVariables["/two"].stateValues.value).eqls([
63
+ "+",
64
+ "d",
65
+ ["^", "b", 2],
66
+ ]);
67
+ });
68
+ });
69
+
70
+ it("substitute into string sugared to math, explicit type", () => {
71
+ cy.window().then(async (win) => {
72
+ win.postMessage(
73
+ {
74
+ doenetML: `
75
+ <text>a</text>
76
+ <substitute type="math" name="s_one" match="x" replacement="b" assignNames="one">
77
+ alpha+x^2
78
+ </substitute>
79
+ <substitute type="math" name="s_two" match="x" replacement="b" assignNames="two">
80
+ <substitute type="math" match="alpha" replacement="d">
81
+ alpha+x^2
82
+ </substitute>
83
+ </substitute>
84
+ `,
85
+ },
86
+ "*",
87
+ );
88
+ });
89
+
90
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
91
+
92
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
93
+ .eq(0)
94
+ .invoke("text")
95
+ .then((text) => {
96
+ expect(text.trim()).equal("α+b2");
97
+ });
98
+ cy.get(cesc("#\\/two") + " .mjx-mrow")
99
+ .eq(0)
100
+ .invoke("text")
101
+ .then((text) => {
102
+ expect(text.trim()).equal("d+b2");
103
+ });
104
+
105
+ cy.window().then(async (win) => {
106
+ let stateVariables = await win.returnAllStateVariables1();
107
+ expect(stateVariables["/s_one"].stateValues.value).eqls([
108
+ "+",
109
+ "alpha",
110
+ ["^", "b", 2],
111
+ ]);
112
+ expect(stateVariables["/one"].stateValues.value).eqls([
113
+ "+",
114
+ "alpha",
115
+ ["^", "b", 2],
116
+ ]);
117
+ expect(stateVariables["/s_two"].stateValues.value).eqls([
118
+ "+",
119
+ "d",
120
+ ["^", "b", 2],
121
+ ]);
122
+ expect(stateVariables["/two"].stateValues.value).eqls([
123
+ "+",
124
+ "d",
125
+ ["^", "b", 2],
126
+ ]);
127
+ });
128
+ });
129
+
130
+ it("substitute into math", () => {
131
+ cy.window().then(async (win) => {
132
+ win.postMessage(
133
+ {
134
+ doenetML: `
135
+ <text>a</text>
136
+ <substitute type="math" name="s_one" match="x" replacement="b" assignNames="one">
137
+ <math>alpha+x^2</math>
138
+ </substitute>
139
+ <substitute type="math" name="s_two" match="x" replacement="b" assignNames="two">
140
+ <substitute type="math" match="alpha" replacement="d">
141
+ <math>alpha+x^2</math>
142
+ </substitute>
143
+ </substitute>
144
+ `,
145
+ },
146
+ "*",
147
+ );
148
+ });
149
+
150
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
151
+
152
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
153
+ .eq(0)
154
+ .invoke("text")
155
+ .then((text) => {
156
+ expect(text.trim()).equal("α+b2");
157
+ });
158
+ cy.get(cesc("#\\/two") + " .mjx-mrow")
159
+ .eq(0)
160
+ .invoke("text")
161
+ .then((text) => {
162
+ expect(text.trim()).equal("d+b2");
163
+ });
164
+
165
+ cy.window().then(async (win) => {
166
+ let stateVariables = await win.returnAllStateVariables1();
167
+ expect(stateVariables["/s_one"].stateValues.value).eqls([
168
+ "+",
169
+ "alpha",
170
+ ["^", "b", 2],
171
+ ]);
172
+ expect(stateVariables["/one"].stateValues.value).eqls([
173
+ "+",
174
+ "alpha",
175
+ ["^", "b", 2],
176
+ ]);
177
+ expect(stateVariables["/s_two"].stateValues.value).eqls([
178
+ "+",
179
+ "d",
180
+ ["^", "b", 2],
181
+ ]);
182
+ expect(stateVariables["/two"].stateValues.value).eqls([
183
+ "+",
184
+ "d",
185
+ ["^", "b", 2],
186
+ ]);
187
+ });
188
+ });
189
+
190
+ it("change simplify", () => {
191
+ cy.window().then(async (win) => {
192
+ win.postMessage(
193
+ {
194
+ doenetML: `
195
+ <text>a</text>
196
+ <textinput name="simplify" prefill="false" />
197
+ <substitute name="s_one" match="x" replacement="y" assignNames="one" simplify="$simplify">
198
+ x+y
199
+ </substitute>
200
+ `,
201
+ },
202
+ "*",
203
+ );
204
+ });
205
+
206
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
207
+
208
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
209
+ .eq(0)
210
+ .invoke("text")
211
+ .then((text) => {
212
+ expect(text.trim()).equal("y+y");
213
+ });
214
+
215
+ cy.window().then(async (win) => {
216
+ let stateVariables = await win.returnAllStateVariables1();
217
+ expect(stateVariables["/s_one"].stateValues.value).eqls(["+", "y", "y"]);
218
+ expect(stateVariables["/one"].stateValues.value).eqls(["+", "y", "y"]);
219
+ });
220
+
221
+ cy.log("set simplify to full");
222
+ cy.get(cesc("#\\/simplify_input")).clear().type("full{enter}");
223
+
224
+ cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "2y");
225
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
226
+ .eq(0)
227
+ .invoke("text")
228
+ .then((text) => {
229
+ expect(text.trim()).equal("2y");
230
+ });
231
+
232
+ cy.window().then(async (win) => {
233
+ let stateVariables = await win.returnAllStateVariables1();
234
+ expect(stateVariables["/s_one"].stateValues.value).eqls(["*", 2, "y"]);
235
+ expect(stateVariables["/one"].stateValues.value).eqls(["*", 2, "y"]);
236
+ });
237
+
238
+ cy.log("set simplify back to none");
239
+ cy.get(cesc("#\\/simplify_input")).clear().type("none{enter}");
240
+
241
+ cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "y+y");
242
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
243
+ .eq(0)
244
+ .invoke("text")
245
+ .then((text) => {
246
+ expect(text.trim()).equal("y+y");
247
+ });
248
+
249
+ cy.window().then(async (win) => {
250
+ let stateVariables = await win.returnAllStateVariables1();
251
+ expect(stateVariables["/s_one"].stateValues.value).eqls(["+", "y", "y"]);
252
+ expect(stateVariables["/one"].stateValues.value).eqls(["+", "y", "y"]);
253
+ });
254
+ });
255
+
256
+ it("substitute with math, global", () => {
257
+ cy.window().then(async (win) => {
258
+ win.postMessage(
259
+ {
260
+ doenetML: `
261
+ <text>a</text>
262
+ <substitute type="math" name="s_one" match="x" replacement="b" assignNames="one">
263
+ <substitute type="math" match="alpha" replacement="d">
264
+ <math>x^2+alpha + x/alpha</math>
265
+ </substitute>
266
+ </substitute>
267
+ `,
268
+ },
269
+ "*",
270
+ );
271
+ });
272
+
273
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
274
+
275
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
276
+ .eq(0)
277
+ .invoke("text")
278
+ .then((text) => {
279
+ expect(text.trim()).equal("b2+d+bd");
280
+ });
281
+
282
+ cy.window().then(async (win) => {
283
+ let stateVariables = await win.returnAllStateVariables1();
284
+ expect(stateVariables["/s_one"].stateValues.value).eqls([
285
+ "+",
286
+ ["^", "b", 2],
287
+ "d",
288
+ ["/", "b", "d"],
289
+ ]);
290
+ expect(stateVariables["/one"].stateValues.value).eqls([
291
+ "+",
292
+ ["^", "b", 2],
293
+ "d",
294
+ ["/", "b", "d"],
295
+ ]);
296
+ });
297
+ });
298
+
299
+ it("change values in math", () => {
300
+ cy.window().then(async (win) => {
301
+ win.postMessage(
302
+ {
303
+ doenetML: `
304
+ <text>a</text>
305
+ <mathinput name="original" prefill="y+x^2"/>
306
+ <mathinput name="match" prefill="x"/>
307
+ <mathinput name="replacement" prefill="b"/>
308
+
309
+ <substitute name="s_one" match="$match" replacement="$replacement" assignNames="one">
310
+ $original
311
+ </substitute>
312
+
313
+ `,
314
+ },
315
+ "*",
316
+ );
317
+ });
318
+
319
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
320
+
321
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
322
+ .eq(0)
323
+ .invoke("text")
324
+ .then((text) => {
325
+ expect(text.trim()).equal("y+b2");
326
+ });
327
+
328
+ cy.window().then(async (win) => {
329
+ let stateVariables = await win.returnAllStateVariables1();
330
+ expect(stateVariables["/s_one"].stateValues.value).eqls([
331
+ "+",
332
+ "y",
333
+ ["^", "b", 2],
334
+ ]);
335
+ expect(stateVariables["/one"].stateValues.value).eqls([
336
+ "+",
337
+ "y",
338
+ ["^", "b", 2],
339
+ ]);
340
+ });
341
+
342
+ cy.log("change original");
343
+ cy.get(cesc("#\\/original") + " textarea").type(
344
+ `{ctrl+home}{shift+end}{backspace}q/x{enter}`,
345
+ { force: true },
346
+ );
347
+
348
+ cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "qb");
349
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
350
+ .eq(0)
351
+ .invoke("text")
352
+ .then((text) => {
353
+ expect(text.trim()).equal("qb");
354
+ });
355
+
356
+ cy.window().then(async (win) => {
357
+ let stateVariables = await win.returnAllStateVariables1();
358
+ expect(stateVariables["/s_one"].stateValues.value).eqls(["/", "q", "b"]);
359
+ expect(stateVariables["/one"].stateValues.value).eqls(["/", "q", "b"]);
360
+ });
361
+
362
+ cy.log("change match so does not match");
363
+ cy.get(cesc("#\\/match") + " textarea").type(
364
+ `{end}{backspace}{backspace}c{enter}`,
365
+ { force: true },
366
+ );
367
+
368
+ cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "qx");
369
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
370
+ .eq(0)
371
+ .invoke("text")
372
+ .then((text) => {
373
+ expect(text.trim()).equal("qx");
374
+ });
375
+
376
+ cy.window().then(async (win) => {
377
+ let stateVariables = await win.returnAllStateVariables1();
378
+ expect(stateVariables["/s_one"].stateValues.value).eqls(["/", "q", "x"]);
379
+ expect(stateVariables["/one"].stateValues.value).eqls(["/", "q", "x"]);
380
+ });
381
+
382
+ cy.log("change match so matches again");
383
+ cy.get(cesc("#\\/match") + " textarea").type(
384
+ `{end}{backspace}{backspace}q{enter}`,
385
+ { force: true },
386
+ );
387
+
388
+ cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "bx");
389
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
390
+ .eq(0)
391
+ .invoke("text")
392
+ .then((text) => {
393
+ expect(text.trim()).equal("bx");
394
+ });
395
+
396
+ cy.window().then(async (win) => {
397
+ let stateVariables = await win.returnAllStateVariables1();
398
+ expect(stateVariables["/s_one"].stateValues.value).eqls(["/", "b", "x"]);
399
+ expect(stateVariables["/one"].stateValues.value).eqls(["/", "b", "x"]);
400
+ });
401
+
402
+ cy.log("change replacement");
403
+ cy.get(cesc("#\\/replacement") + " textarea").type(
404
+ `{end}{backspace}{backspace}m^2{enter}`,
405
+ { force: true },
406
+ );
407
+
408
+ cy.get(cesc("#\\/one") + " .mjx-mrow").should("contain.text", "m2x");
409
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
410
+ .eq(0)
411
+ .invoke("text")
412
+ .then((text) => {
413
+ expect(text.trim()).equal("m2x");
414
+ });
415
+
416
+ cy.window().then(async (win) => {
417
+ let stateVariables = await win.returnAllStateVariables1();
418
+ expect(stateVariables["/s_one"].stateValues.value).eqls([
419
+ "/",
420
+ ["^", "m", 2],
421
+ "x",
422
+ ]);
423
+ expect(stateVariables["/one"].stateValues.value).eqls([
424
+ "/",
425
+ ["^", "m", 2],
426
+ "x",
427
+ ]);
428
+ });
429
+ });
430
+
431
+ // Is the desired behavior? It is how substitute works in math-expressinons.
432
+ it("substitute does not change numbers in math", () => {
433
+ cy.window().then(async (win) => {
434
+ win.postMessage(
435
+ {
436
+ doenetML: `
437
+ <text>a</text>
438
+ <substitute name="s_one" match="1" replacement="2" assignNames="one">
439
+ x+1
440
+ </substitute>
441
+ <substitute name="s_two" match="x" replacement="y" assignNames="two">
442
+ x+1
443
+ </substitute>
444
+ `,
445
+ },
446
+ "*",
447
+ );
448
+ });
449
+
450
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
451
+
452
+ cy.get(cesc("#\\/one") + " .mjx-mrow")
453
+ .eq(0)
454
+ .invoke("text")
455
+ .then((text) => {
456
+ expect(text.trim()).equal("x+1");
457
+ });
458
+ cy.get(cesc("#\\/two") + " .mjx-mrow")
459
+ .eq(0)
460
+ .invoke("text")
461
+ .then((text) => {
462
+ expect(text.trim()).equal("y+1");
463
+ });
464
+
465
+ cy.window().then(async (win) => {
466
+ let stateVariables = await win.returnAllStateVariables1();
467
+ expect(stateVariables["/s_one"].stateValues.value).eqls(["+", "x", 1]);
468
+ expect(stateVariables["/one"].stateValues.value).eqls(["+", "x", 1]);
469
+ expect(stateVariables["/s_two"].stateValues.value).eqls(["+", "y", 1]);
470
+ expect(stateVariables["/two"].stateValues.value).eqls(["+", "y", 1]);
471
+ });
472
+ });
473
+
474
+ it("substitute into string sugared to text", () => {
475
+ cy.window().then(async (win) => {
476
+ win.postMessage(
477
+ {
478
+ doenetML: `
479
+ <text>a</text>
480
+ <substitute name="s_one" type="text" match="Be" replacement="cHe" assignNames="one">
481
+ Big banana BerAtes brown bErry.
482
+ </substitute>
483
+ <substitute name="s_two" type="text" match="Be" replacement="cHe" assignNames="two">
484
+ <substitute type="text" match=" berateS " replacement=" chideS">
485
+ Big banana BerAtes brown bErry.
486
+ </substitute>
487
+ </substitute>
488
+ `,
489
+ },
490
+ "*",
491
+ );
492
+ });
493
+
494
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
495
+
496
+ let s1 = "Big banana cHerAtes brown cHerry.";
497
+ let s2 = "Big banana chideSbrown cHerry.";
498
+
499
+ cy.get(cesc("#\\/one")).should("contain.text", s1);
500
+ cy.get(cesc("#\\/two")).should("contain.text", s2);
501
+
502
+ cy.window().then(async (win) => {
503
+ let stateVariables = await win.returnAllStateVariables1();
504
+ expect(stateVariables["/s_one"].stateValues.value.trim()).eq(s1);
505
+ expect(stateVariables["/one"].stateValues.value.trim()).eq(s1);
506
+ expect(stateVariables["/s_two"].stateValues.value.trim()).eq(s2);
507
+ expect(stateVariables["/two"].stateValues.value.trim()).eq(s2);
508
+ });
509
+ });
510
+
511
+ it("substitute into text", () => {
512
+ cy.window().then(async (win) => {
513
+ win.postMessage(
514
+ {
515
+ doenetML: `
516
+ <text>a</text>
517
+ <substitute name="s_one" type="text" match="Be" replacement="cHe" assignNames="one">
518
+ <text>Big banana BerAtes brown bErry.</text>
519
+ </substitute>
520
+ <substitute name="s_two" type="text" match="Be" replacement="cHe" assignNames="two">
521
+ <substitute type="text" match=" berateS " replacement=" chideS">
522
+ <text>Big banana BerAtes brown bErry.</text>
523
+ </substitute>
524
+ </substitute>
525
+ `,
526
+ },
527
+ "*",
528
+ );
529
+ });
530
+
531
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
532
+
533
+ let s1 = "Big banana cHerAtes brown cHerry.";
534
+ let s2 = "Big banana chideSbrown cHerry.";
535
+
536
+ cy.get(cesc("#\\/one")).should("have.text", s1);
537
+ cy.get(cesc("#\\/two")).should("have.text", s2);
538
+
539
+ cy.window().then(async (win) => {
540
+ let stateVariables = await win.returnAllStateVariables1();
541
+ expect(stateVariables["/s_one"].stateValues.value).eq(s1);
542
+ expect(stateVariables["/one"].stateValues.value).eq(s1);
543
+ expect(stateVariables["/s_two"].stateValues.value).eq(s2);
544
+ expect(stateVariables["/two"].stateValues.value).eq(s2);
545
+ });
546
+ });
547
+
548
+ it("substitute into text, match case", () => {
549
+ cy.window().then(async (win) => {
550
+ win.postMessage(
551
+ {
552
+ doenetML: `
553
+ <text>a</text>
554
+ <substitute matchCase name="s_one" type="text" match="Be" replacement="cHe" assignNames="one">
555
+ <text>Big banana BerAtes brown bErry.</text>
556
+ </substitute>
557
+ <substitute matchCase name="s_two" type="text" match="bE" replacement="cHe" assignNames="two">
558
+ <text>Big banana BerAtes brown bErry.</text>
559
+ </substitute>
560
+ `,
561
+ },
562
+ "*",
563
+ );
564
+ });
565
+
566
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
567
+
568
+ let s1 = "Big banana cHerAtes brown bErry.";
569
+ let s2 = "Big banana BerAtes brown cHerry.";
570
+
571
+ cy.get(cesc("#\\/one")).should("have.text", s1);
572
+ cy.get(cesc("#\\/two")).should("have.text", s2);
573
+
574
+ cy.window().then(async (win) => {
575
+ let stateVariables = await win.returnAllStateVariables1();
576
+ expect(stateVariables["/s_one"].stateValues.value).eq(s1);
577
+ expect(stateVariables["/one"].stateValues.value).eq(s1);
578
+ expect(stateVariables["/s_two"].stateValues.value).eq(s2);
579
+ expect(stateVariables["/two"].stateValues.value).eq(s2);
580
+ });
581
+ });
582
+
583
+ it("substitute into text, preserve case", () => {
584
+ cy.window().then(async (win) => {
585
+ win.postMessage(
586
+ {
587
+ doenetML: `
588
+ <text>a</text>
589
+ <substitute preserveCase name="s_one" type="text" match="word" replacement="new" assignNames="one">
590
+ <text>A word WORD Word wOrD WoRd.</text>
591
+ </substitute>
592
+ <substitute preserveCase name="s_two" type="text" match="word" replacement="NEW" assignNames="two">
593
+ <text>A word WORD Word wOrD WoRd.</text>
594
+ </substitute>
595
+ <substitute preserveCase name="s_three" type="text" match="word" replacement="NeW" assignNames="three">
596
+ <text>A word WORD Word wOrD WoRd.</text>
597
+ </substitute>
598
+ `,
599
+ },
600
+ "*",
601
+ );
602
+ });
603
+
604
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
605
+
606
+ let s1 = "A new NEW New new New.";
607
+ let s2 = "A new NEW NEW nEW NEW.";
608
+ let s3 = "A new NEW NeW neW NeW.";
609
+
610
+ cy.get(cesc("#\\/one")).should("have.text", s1);
611
+ cy.get(cesc("#\\/two")).should("have.text", s2);
612
+ cy.get(cesc("#\\/three")).should("have.text", s3);
613
+
614
+ cy.window().then(async (win) => {
615
+ let stateVariables = await win.returnAllStateVariables1();
616
+ expect(stateVariables["/s_one"].stateValues.value).eq(s1);
617
+ expect(stateVariables["/one"].stateValues.value).eq(s1);
618
+ expect(stateVariables["/s_two"].stateValues.value).eq(s2);
619
+ expect(stateVariables["/two"].stateValues.value).eq(s2);
620
+ expect(stateVariables["/s_three"].stateValues.value).eq(s3);
621
+ expect(stateVariables["/three"].stateValues.value).eq(s3);
622
+ });
623
+ });
624
+
625
+ it("substitute into text, match whole word", () => {
626
+ cy.window().then(async (win) => {
627
+ win.postMessage(
628
+ {
629
+ doenetML: `
630
+ <text>a</text>
631
+ <substitute matchWholeWord name="s_one" type="text" match="Be" replacement="cHe" assignNames="one">
632
+ <text>Big banana BerAtes brown bErry.</text>
633
+ </substitute>
634
+ <substitute matchWholeWord name="s_two" type="text" match="berateS" replacement="chideS" assignNames="two">
635
+ <text>Big banana BerAtes brown bErry.</text>
636
+ </substitute>
637
+ `,
638
+ },
639
+ "*",
640
+ );
641
+ });
642
+
643
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
644
+
645
+ let s1 = "Big banana BerAtes brown bErry.";
646
+ let s2 = "Big banana chideS brown bErry.";
647
+
648
+ cy.get(cesc("#\\/one")).should("have.text", s1);
649
+ cy.get(cesc("#\\/two")).should("have.text", s2);
650
+
651
+ cy.window().then(async (win) => {
652
+ let stateVariables = await win.returnAllStateVariables1();
653
+ expect(stateVariables["/s_one"].stateValues.value).eq(s1);
654
+ expect(stateVariables["/one"].stateValues.value).eq(s1);
655
+ expect(stateVariables["/s_two"].stateValues.value).eq(s2);
656
+ expect(stateVariables["/two"].stateValues.value).eq(s2);
657
+ });
658
+ });
659
+
660
+ it("substitute into text, match whole word with spaces", () => {
661
+ cy.window().then(async (win) => {
662
+ win.postMessage(
663
+ {
664
+ doenetML: `
665
+ <text>a</text>
666
+ <substitute matchWholeWord name="s_one" type="text" match=" Be" replacement="cHe" assignNames="one">
667
+ <text>Big banana BerAtes brown bErry.</text>
668
+ </substitute>
669
+ <substitute matchWholeWord name="s_two" type="text" match=" berateS " replacement="chideS" assignNames="two">
670
+ <text>Big banana BerAtes brown bErry.</text>
671
+ </substitute>
672
+ `,
673
+ },
674
+ "*",
675
+ );
676
+ });
677
+
678
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
679
+
680
+ let s1 = "Big banana BerAtes brown bErry.";
681
+ let s2 = "Big bananachideSbrown bErry.";
682
+
683
+ cy.get(cesc("#\\/one")).should("have.text", s1);
684
+ cy.get(cesc("#\\/two")).should("have.text", s2);
685
+
686
+ cy.window().then(async (win) => {
687
+ let stateVariables = await win.returnAllStateVariables1();
688
+ expect(stateVariables["/s_one"].stateValues.value).eq(s1);
689
+ expect(stateVariables["/one"].stateValues.value).eq(s1);
690
+ expect(stateVariables["/s_two"].stateValues.value).eq(s2);
691
+ expect(stateVariables["/two"].stateValues.value).eq(s2);
692
+ });
693
+ });
694
+
695
+ it("substitute into text, global", () => {
696
+ cy.window().then(async (win) => {
697
+ win.postMessage(
698
+ {
699
+ doenetML: `
700
+ <text>a</text>
701
+ <substitute name="s_one" type="text" match="b" replacement="c" assignNames="one">
702
+ <text>Big babana BerAtes brown bErry.</text>
703
+ </substitute>
704
+ `,
705
+ },
706
+ "*",
707
+ );
708
+ });
709
+
710
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
711
+
712
+ let s1 = "cig cacana cerAtes crown cErry.";
713
+
714
+ cy.get(cesc("#\\/one")).should("have.text", s1);
715
+
716
+ cy.window().then(async (win) => {
717
+ let stateVariables = await win.returnAllStateVariables1();
718
+ expect(stateVariables["/s_one"].stateValues.value).eq(s1);
719
+ expect(stateVariables["/one"].stateValues.value).eq(s1);
720
+ });
721
+ });
722
+
723
+ it("change pattern and replaces in text", () => {
724
+ cy.window().then(async (win) => {
725
+ win.postMessage(
726
+ {
727
+ doenetML: `
728
+ <text>a</text>
729
+ <textinput name="original" prefill="Big banana BerAtes brown bErry."/>
730
+ <textinput name="match" prefill="Be"/>
731
+ <textinput name="replacement" prefill="cHe"/>
732
+
733
+ <substitute type="text" name="s_one" match="$match" replacement="$replacement" assignNames="one">
734
+ <text>$original</text>
735
+ </substitute>
736
+
737
+ `,
738
+ },
739
+ "*",
740
+ );
741
+ });
742
+
743
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
744
+
745
+ let s1 = "Big banana cHerAtes brown cHerry.";
746
+
747
+ cy.get(cesc("#\\/one")).should("have.text", s1);
748
+
749
+ cy.window().then(async (win) => {
750
+ let stateVariables = await win.returnAllStateVariables1();
751
+ expect(stateVariables["/s_one"].stateValues.value).eq(s1);
752
+ expect(stateVariables["/one"].stateValues.value).eq(s1);
753
+ });
754
+
755
+ cy.log("change original");
756
+ cy.get(cesc("#\\/original_input"))
757
+ .clear()
758
+ .type(`The bicycle belongs to me.{enter}`);
759
+ let s2 = "The bicycle cHelongs to me.";
760
+ cy.get(cesc("#\\/one")).should("have.text", s2);
761
+
762
+ cy.window().then(async (win) => {
763
+ let stateVariables = await win.returnAllStateVariables1();
764
+ expect(stateVariables["/s_one"].stateValues.value).eq(s2);
765
+ expect(stateVariables["/one"].stateValues.value).eq(s2);
766
+ });
767
+
768
+ cy.log("change match so does not match");
769
+ cy.get(cesc("#\\/match_input")).clear().type(`bike{enter}`);
770
+ let s3 = "The bicycle belongs to me.";
771
+ cy.get(cesc("#\\/one")).should("have.text", s3);
772
+
773
+ cy.window().then(async (win) => {
774
+ let stateVariables = await win.returnAllStateVariables1();
775
+ expect(stateVariables["/s_one"].stateValues.value).eq(s3);
776
+ expect(stateVariables["/one"].stateValues.value).eq(s3);
777
+ });
778
+
779
+ cy.log("change match so matches again");
780
+ cy.get(cesc("#\\/match_input")).clear().type(`e b{enter}`);
781
+ let s4 = "ThcHeicyclcHeelongs to me.";
782
+ cy.get(cesc("#\\/one")).should("have.text", s4);
783
+
784
+ cy.window().then(async (win) => {
785
+ let stateVariables = await win.returnAllStateVariables1();
786
+ expect(stateVariables["/s_one"].stateValues.value).eq(s4);
787
+ expect(stateVariables["/one"].stateValues.value).eq(s4);
788
+ });
789
+
790
+ cy.log("change match and replacement");
791
+ cy.get(cesc("#\\/match_input")).clear().type(`bicycle{enter}`);
792
+ cy.get(cesc("#\\/replacement_input")).clear().type(`scooter{enter}`);
793
+ let s5 = "The scooter belongs to me.";
794
+ cy.get(cesc("#\\/one")).should("have.text", s5);
795
+
796
+ cy.window().then(async (win) => {
797
+ let stateVariables = await win.returnAllStateVariables1();
798
+ expect(stateVariables["/s_one"].stateValues.value).eq(s5);
799
+ expect(stateVariables["/one"].stateValues.value).eq(s5);
800
+ });
801
+ });
802
+
803
+ it("modify in inverse direction, math", () => {
804
+ cy.window().then(async (win) => {
805
+ win.postMessage(
806
+ {
807
+ doenetML: `
808
+ <text>a</text>
809
+ <p>Original: <mathinput name="orig" prefill="x^2+2x+3y" /></p>
810
+ <p>Original 2:<math name="orig2">$orig</math></p>
811
+
812
+ <p>Match: <mathinput name="match" prefill="x"/></p>
813
+ <p>Replacement: <mathinput name="replacement" prefill="b"/></p>
814
+
815
+ <p>Substituted: <substitute match="$match" replacement="$replacement" assignNames="subbed" name="s">$orig2</substitute></p>
816
+
817
+ <p>Substituted 2: <mathinput name="subbed2" bindValueTo="$subbed" /></p>
818
+
819
+
820
+ `,
821
+ },
822
+ "*",
823
+ );
824
+ });
825
+
826
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
827
+
828
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
829
+ .invoke("text")
830
+ .then((text) => {
831
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x2+2x+3y");
832
+ });
833
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
834
+ .eq(0)
835
+ .invoke("text")
836
+ .then((text) => {
837
+ expect(text.trim()).equal("x2+2x+3y");
838
+ });
839
+
840
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
841
+ .eq(0)
842
+ .invoke("text")
843
+ .then((text) => {
844
+ expect(text.trim()).equal("b2+2b+3y");
845
+ });
846
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
847
+ .invoke("text")
848
+ .then((text) => {
849
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("b2+2b+3y");
850
+ });
851
+
852
+ cy.window().then(async (win) => {
853
+ let stateVariables = await win.returnAllStateVariables1();
854
+ let origExpr = me.fromText("x^2+2x+3y").tree;
855
+ let subbedExpr = me.fromText("b^2+2b+3y").tree;
856
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
857
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
858
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
859
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
860
+ });
861
+
862
+ cy.log("change original");
863
+ cy.get(cesc("#\\/orig") + " textarea").type(`{end}{backspace}x{enter}`, {
864
+ force: true,
865
+ });
866
+
867
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow").should("contain.text", "x2+2x+3x");
868
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should(
869
+ "contain.text",
870
+ "b2+2b+3b",
871
+ );
872
+
873
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
874
+ .invoke("text")
875
+ .then((text) => {
876
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x2+2x+3x");
877
+ });
878
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
879
+ .eq(0)
880
+ .invoke("text")
881
+ .then((text) => {
882
+ expect(text.trim()).equal("x2+2x+3x");
883
+ });
884
+
885
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
886
+ .eq(0)
887
+ .invoke("text")
888
+ .then((text) => {
889
+ expect(text.trim()).equal("b2+2b+3b");
890
+ });
891
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
892
+ .invoke("text")
893
+ .then((text) => {
894
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("b2+2b+3b");
895
+ });
896
+
897
+ cy.window().then(async (win) => {
898
+ let stateVariables = await win.returnAllStateVariables1();
899
+ let origExpr = me.fromText("x^2+2x+3x").tree;
900
+ let subbedExpr = me.fromText("b^2+2b+3b").tree;
901
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
902
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
903
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
904
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
905
+ });
906
+
907
+ cy.log("change subbed");
908
+ cy.get(cesc("#\\/subbed2") + " textarea").type(
909
+ `{end}{backspace}v/b{enter}`,
910
+ { force: true },
911
+ );
912
+
913
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow").should(
914
+ "contain.text",
915
+ "x2+2x+3vx",
916
+ );
917
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should(
918
+ "contain.text",
919
+ "b2+2b+3vb",
920
+ );
921
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
922
+ .invoke("text")
923
+ .then((text) => {
924
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x2+2x+3vx");
925
+ });
926
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
927
+ .eq(0)
928
+ .invoke("text")
929
+ .then((text) => {
930
+ expect(text.trim()).equal("x2+2x+3vx");
931
+ });
932
+
933
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
934
+ .eq(0)
935
+ .invoke("text")
936
+ .then((text) => {
937
+ expect(text.trim()).equal("b2+2b+3vb");
938
+ });
939
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
940
+ .invoke("text")
941
+ .then((text) => {
942
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("b2+2b+3vb");
943
+ });
944
+
945
+ cy.window().then(async (win) => {
946
+ let stateVariables = await win.returnAllStateVariables1();
947
+ let origExpr = me.fromText("x^2+2x+3v/x").tree;
948
+ let subbedExpr = me.fromText("b^2+2b+3v/b").tree;
949
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
950
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
951
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
952
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
953
+ });
954
+
955
+ cy.log("change replacement so that it is in original");
956
+ cy.get(cesc("#\\/replacement") + " textarea").type(
957
+ `{end}{backspace}v{enter}`,
958
+ { force: true },
959
+ );
960
+
961
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow").should(
962
+ "contain.text",
963
+ "v2+2v+3vv",
964
+ );
965
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should(
966
+ "contain.text",
967
+ "v2+2v+3vv",
968
+ );
969
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
970
+ .invoke("text")
971
+ .then((text) => {
972
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x2+2x+3vx");
973
+ });
974
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
975
+ .eq(0)
976
+ .invoke("text")
977
+ .then((text) => {
978
+ expect(text.trim()).equal("x2+2x+3vx");
979
+ });
980
+
981
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
982
+ .eq(0)
983
+ .invoke("text")
984
+ .then((text) => {
985
+ expect(text.trim()).equal("v2+2v+3vv");
986
+ });
987
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
988
+ .invoke("text")
989
+ .then((text) => {
990
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("v2+2v+3vv");
991
+ });
992
+
993
+ cy.window().then(async (win) => {
994
+ let stateVariables = await win.returnAllStateVariables1();
995
+ let origExpr = me.fromText("x^2+2x+3v/x").tree;
996
+ let subbedExpr = me.fromText("v^2+2v+3v/v").tree;
997
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
998
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
999
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1000
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1001
+ });
1002
+
1003
+ cy.log("Cannot modify subbed");
1004
+ cy.get(cesc("#\\/subbed2") + " textarea").type(
1005
+ `{end}{backspace}+1{enter}`,
1006
+ { force: true },
1007
+ );
1008
+
1009
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should(
1010
+ "not.contain.text",
1011
+ "v2+2v+3vv+1",
1012
+ );
1013
+
1014
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1015
+ .invoke("text")
1016
+ .then((text) => {
1017
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x2+2x+3vx");
1018
+ });
1019
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1020
+ .eq(0)
1021
+ .invoke("text")
1022
+ .then((text) => {
1023
+ expect(text.trim()).equal("x2+2x+3vx");
1024
+ });
1025
+
1026
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1027
+ .eq(0)
1028
+ .invoke("text")
1029
+ .then((text) => {
1030
+ expect(text.trim()).equal("v2+2v+3vv");
1031
+ });
1032
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1033
+ .invoke("text")
1034
+ .then((text) => {
1035
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("v2+2v+3vv");
1036
+ });
1037
+
1038
+ cy.window().then(async (win) => {
1039
+ let stateVariables = await win.returnAllStateVariables1();
1040
+ let origExpr = me.fromText("x^2+2x+3v/x").tree;
1041
+ let subbedExpr = me.fromText("v^2+2v+3v/v").tree;
1042
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1043
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1044
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1045
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1046
+ });
1047
+
1048
+ cy.log("change original to not contain replacement");
1049
+ cy.get(cesc("#\\/orig") + " textarea").type(
1050
+ `{end}{leftArrow}{leftArrow}{leftArrow}{backspace}u{enter}`,
1051
+ { force: true },
1052
+ );
1053
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow").should(
1054
+ "contain.text",
1055
+ "x2+2x+3ux",
1056
+ );
1057
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should(
1058
+ "contain.text",
1059
+ "v2+2v+3uv",
1060
+ );
1061
+
1062
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1063
+ .invoke("text")
1064
+ .then((text) => {
1065
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x2+2x+3ux");
1066
+ });
1067
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1068
+ .eq(0)
1069
+ .invoke("text")
1070
+ .then((text) => {
1071
+ expect(text.trim()).equal("x2+2x+3ux");
1072
+ });
1073
+
1074
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1075
+ .eq(0)
1076
+ .invoke("text")
1077
+ .then((text) => {
1078
+ expect(text.trim()).equal("v2+2v+3uv");
1079
+ });
1080
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1081
+ .invoke("text")
1082
+ .then((text) => {
1083
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("v2+2v+3uv");
1084
+ });
1085
+
1086
+ cy.window().then(async (win) => {
1087
+ let stateVariables = await win.returnAllStateVariables1();
1088
+ let origExpr = me.fromText("x^2+2x+3u/x").tree;
1089
+ let subbedExpr = me.fromText("v^2+2v+3u/v").tree;
1090
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1091
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1092
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1093
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1094
+ });
1095
+
1096
+ cy.log("Can modify subbed again");
1097
+ cy.get(cesc("#\\/subbed2") + " textarea").type(
1098
+ `{home}{rightArrow}{rightArrow}{rightArrow}{backspace}5{enter}`,
1099
+ { force: true },
1100
+ );
1101
+
1102
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow").should(
1103
+ "contain.text",
1104
+ "x5+2x+3ux",
1105
+ );
1106
+
1107
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1108
+ .invoke("text")
1109
+ .then((text) => {
1110
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x5+2x+3ux");
1111
+ });
1112
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1113
+ .eq(0)
1114
+ .invoke("text")
1115
+ .then((text) => {
1116
+ expect(text.trim()).equal("x5+2x+3ux");
1117
+ });
1118
+
1119
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1120
+ .eq(0)
1121
+ .invoke("text")
1122
+ .then((text) => {
1123
+ expect(text.trim()).equal("v5+2v+3uv");
1124
+ });
1125
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1126
+ .invoke("text")
1127
+ .then((text) => {
1128
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("v5+2v+3uv");
1129
+ });
1130
+
1131
+ cy.window().then(async (win) => {
1132
+ let stateVariables = await win.returnAllStateVariables1();
1133
+ let origExpr = me.fromText("x^5+2x+3u/x").tree;
1134
+ let subbedExpr = me.fromText("v^5+2v+3u/v").tree;
1135
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1136
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1137
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1138
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1139
+ });
1140
+
1141
+ cy.log("change replacement to be more than a variable");
1142
+ cy.get(cesc("#\\/replacement") + " textarea").type(`{end}+1{enter}`, {
1143
+ force: true,
1144
+ });
1145
+
1146
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow").should(
1147
+ "contain.text",
1148
+ "(v+1)5+2(v+1)+3uv+1",
1149
+ );
1150
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should(
1151
+ "contain.text",
1152
+ "(v+1)5+2(v+1)+3uv+1",
1153
+ );
1154
+
1155
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1156
+ .invoke("text")
1157
+ .then((text) => {
1158
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x5+2x+3ux");
1159
+ });
1160
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1161
+ .eq(0)
1162
+ .invoke("text")
1163
+ .then((text) => {
1164
+ expect(text.trim()).equal("x5+2x+3ux");
1165
+ });
1166
+
1167
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1168
+ .eq(0)
1169
+ .invoke("text")
1170
+ .then((text) => {
1171
+ expect(text.trim()).equal("(v+1)5+2(v+1)+3uv+1");
1172
+ });
1173
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1174
+ .invoke("text")
1175
+ .then((text) => {
1176
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1177
+ "(v+1)5+2(v+1)+3uv+1",
1178
+ );
1179
+ });
1180
+
1181
+ cy.window().then(async (win) => {
1182
+ let stateVariables = await win.returnAllStateVariables1();
1183
+ let origExpr = me.fromText("x^5+2x+3u/x").tree;
1184
+ let subbedExpr = me.fromText("(v+1)^5+2(v+1)+3u/(v+1)").tree;
1185
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1186
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1187
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1188
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1189
+ });
1190
+
1191
+ cy.log("Cannot modify subbed");
1192
+ cy.get(cesc("#\\/subbed2") + " textarea").type(`{home}+7{enter}`, {
1193
+ force: true,
1194
+ });
1195
+
1196
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should(
1197
+ "not.contain.text",
1198
+ "+7",
1199
+ );
1200
+
1201
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1202
+ .invoke("text")
1203
+ .then((text) => {
1204
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x5+2x+3ux");
1205
+ });
1206
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1207
+ .eq(0)
1208
+ .invoke("text")
1209
+ .then((text) => {
1210
+ expect(text.trim()).equal("x5+2x+3ux");
1211
+ });
1212
+
1213
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1214
+ .eq(0)
1215
+ .invoke("text")
1216
+ .then((text) => {
1217
+ expect(text.trim()).equal("(v+1)5+2(v+1)+3uv+1");
1218
+ });
1219
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1220
+ .invoke("text")
1221
+ .then((text) => {
1222
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1223
+ "(v+1)5+2(v+1)+3uv+1",
1224
+ );
1225
+ });
1226
+
1227
+ cy.window().then(async (win) => {
1228
+ let stateVariables = await win.returnAllStateVariables1();
1229
+ let origExpr = me.fromText("x^5+2x+3u/x").tree;
1230
+ let subbedExpr = me.fromText("(v+1)^5+2(v+1)+3u/(v+1)").tree;
1231
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1232
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1233
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1234
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1235
+ });
1236
+
1237
+ cy.log("change replacement to involve a subscript");
1238
+ cy.get(cesc("#\\/replacement") + " textarea").type(
1239
+ `{end}{backspace}{backspace}_3{enter}`,
1240
+ { force: true },
1241
+ );
1242
+
1243
+ cy.waitUntil(() =>
1244
+ cy
1245
+ .get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1246
+ .invoke("text")
1247
+ .then(
1248
+ (text) =>
1249
+ text.replace(/[\s\u200B-\u200D\uFEFF]/g, "") === "v53+2v3+3uv3",
1250
+ ),
1251
+ );
1252
+
1253
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1254
+ .invoke("text")
1255
+ .then((text) => {
1256
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal("x5+2x+3ux");
1257
+ });
1258
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1259
+ .eq(0)
1260
+ .invoke("text")
1261
+ .then((text) => {
1262
+ expect(text.trim()).equal("x5+2x+3ux");
1263
+ });
1264
+
1265
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1266
+ .eq(0)
1267
+ .invoke("text")
1268
+ .then((text) => {
1269
+ expect(text.trim()).equal("v53+2v3+3uv3");
1270
+ });
1271
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1272
+ .invoke("text")
1273
+ .then((text) => {
1274
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1275
+ "v53+2v3+3uv3",
1276
+ );
1277
+ });
1278
+
1279
+ cy.window().then(async (win) => {
1280
+ let stateVariables = await win.returnAllStateVariables1();
1281
+ let origExpr = me.fromText("x^5+2x+3u/x").tree;
1282
+ let subbedExpr = me.fromText("v_3^5+2v_3+3u/v_3").tree;
1283
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1284
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1285
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1286
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1287
+ });
1288
+
1289
+ cy.log("Can modify subbed once more");
1290
+ cy.get(cesc("#\\/subbed2") + " textarea").type(
1291
+ `{home}{rightArrow}{rightArrow}{rightArrow}{backspace}9{enter}`,
1292
+ { force: true },
1293
+ );
1294
+
1295
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow").should(
1296
+ "contain.text",
1297
+ "v59+2v3+3uv3",
1298
+ );
1299
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1300
+ .invoke("text")
1301
+ .then((text) => {
1302
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1303
+ "v59+2x+3ux",
1304
+ );
1305
+ });
1306
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1307
+ .eq(0)
1308
+ .invoke("text")
1309
+ .then((text) => {
1310
+ expect(text.trim()).equal("v59+2x+3ux");
1311
+ });
1312
+
1313
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1314
+ .eq(0)
1315
+ .invoke("text")
1316
+ .then((text) => {
1317
+ expect(text.trim()).equal("v59+2v3+3uv3");
1318
+ });
1319
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1320
+ .invoke("text")
1321
+ .then((text) => {
1322
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1323
+ "v59+2v3+3uv3",
1324
+ );
1325
+ });
1326
+
1327
+ cy.window().then(async (win) => {
1328
+ let stateVariables = await win.returnAllStateVariables1();
1329
+ let origExpr = me.fromText("v_9^5+2x+3u/x").tree;
1330
+ let subbedExpr = me.fromText("v_9^5+2v_3+3u/v_3").tree;
1331
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1332
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1333
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1334
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1335
+ });
1336
+
1337
+ cy.log("change match to involve a subscript");
1338
+ cy.get(cesc("#\\/match") + " textarea").type(`{end}{backspace}v_9{enter}`, {
1339
+ force: true,
1340
+ });
1341
+
1342
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow").should(
1343
+ "contain.text",
1344
+ "v53+2x+3ux",
1345
+ );
1346
+
1347
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1348
+ .invoke("text")
1349
+ .then((text) => {
1350
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1351
+ "v59+2x+3ux",
1352
+ );
1353
+ });
1354
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1355
+ .eq(0)
1356
+ .invoke("text")
1357
+ .then((text) => {
1358
+ expect(text.trim()).equal("v59+2x+3ux");
1359
+ });
1360
+
1361
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1362
+ .eq(0)
1363
+ .invoke("text")
1364
+ .then((text) => {
1365
+ expect(text.trim()).equal("v53+2x+3ux");
1366
+ });
1367
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1368
+ .invoke("text")
1369
+ .then((text) => {
1370
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1371
+ "v53+2x+3ux",
1372
+ );
1373
+ });
1374
+
1375
+ cy.window().then(async (win) => {
1376
+ let stateVariables = await win.returnAllStateVariables1();
1377
+ let origExpr = me.fromText("v_9^5+2x+3u/x").tree;
1378
+ let subbedExpr = me.fromText("v_3^5+2x+3u/x").tree;
1379
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1380
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1381
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1382
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1383
+ });
1384
+
1385
+ cy.log("Can still modify subbed");
1386
+ cy.get(cesc("#\\/subbed2") + " textarea").type(
1387
+ `{end}{leftArrow}{backspace}v_3{enter}`,
1388
+ { force: true },
1389
+ );
1390
+
1391
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow").should(
1392
+ "contain.text",
1393
+ "v53+2x+3uv3",
1394
+ );
1395
+
1396
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1397
+ .invoke("text")
1398
+ .then((text) => {
1399
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1400
+ "v59+2x+3uv9",
1401
+ );
1402
+ });
1403
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1404
+ .eq(0)
1405
+ .invoke("text")
1406
+ .then((text) => {
1407
+ expect(text.trim()).equal("v59+2x+3uv9");
1408
+ });
1409
+
1410
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1411
+ .eq(0)
1412
+ .invoke("text")
1413
+ .then((text) => {
1414
+ expect(text.trim()).equal("v53+2x+3uv3");
1415
+ });
1416
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1417
+ .invoke("text")
1418
+ .then((text) => {
1419
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1420
+ "v53+2x+3uv3",
1421
+ );
1422
+ });
1423
+
1424
+ cy.window().then(async (win) => {
1425
+ let stateVariables = await win.returnAllStateVariables1();
1426
+ let origExpr = me.fromText("v_9^5+2x+3u/v_9").tree;
1427
+ let subbedExpr = me.fromText("v_3^5+2x+3u/v_3").tree;
1428
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1429
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1430
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1431
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1432
+ });
1433
+
1434
+ cy.log("Cannot modify subbed to include match");
1435
+ cy.get(cesc("#\\/subbed2") + " textarea").type(`{end}+v_9{enter}`, {
1436
+ force: true,
1437
+ });
1438
+
1439
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`).should(
1440
+ "not.contain.text",
1441
+ "+v9",
1442
+ );
1443
+
1444
+ cy.get(cesc(`#\\/orig`) + ` .mq-editable-field`)
1445
+ .invoke("text")
1446
+ .then((text) => {
1447
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1448
+ "v59+2x+3uv9",
1449
+ );
1450
+ });
1451
+ cy.get(cesc("#\\/orig2") + " .mjx-mrow")
1452
+ .eq(0)
1453
+ .invoke("text")
1454
+ .then((text) => {
1455
+ expect(text.trim()).equal("v59+2x+3uv9");
1456
+ });
1457
+
1458
+ cy.get(cesc("#\\/subbed") + " .mjx-mrow")
1459
+ .eq(0)
1460
+ .invoke("text")
1461
+ .then((text) => {
1462
+ expect(text.trim()).equal("v53+2x+3uv3");
1463
+ });
1464
+ cy.get(cesc(`#\\/subbed2`) + ` .mq-editable-field`)
1465
+ .invoke("text")
1466
+ .then((text) => {
1467
+ expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal(
1468
+ "v53+2x+3uv3",
1469
+ );
1470
+ });
1471
+
1472
+ cy.window().then(async (win) => {
1473
+ let stateVariables = await win.returnAllStateVariables1();
1474
+ let origExpr = me.fromText("v_9^5+2x+3u/v_9").tree;
1475
+ let subbedExpr = me.fromText("v_3^5+2x+3u/v_3").tree;
1476
+ expect(stateVariables["/orig"].stateValues.value).eqls(origExpr);
1477
+ expect(stateVariables["/orig2"].stateValues.value).eqls(origExpr);
1478
+ expect(stateVariables["/subbed"].stateValues.value).eqls(subbedExpr);
1479
+ expect(stateVariables["/subbed2"].stateValues.value).eqls(subbedExpr);
1480
+ });
1481
+ });
1482
+
1483
+ it("modify in inverse direction, text", () => {
1484
+ cy.window().then(async (win) => {
1485
+ win.postMessage(
1486
+ {
1487
+ doenetML: `
1488
+ <text>a</text>
1489
+ <p>Original: <textinput name="orig" prefill="hello there" size="20" /></p>
1490
+ <p>Original 2:<text name="orig2">$orig</text></p>
1491
+
1492
+ <p>Match: <textinput name="match" prefill="hello"/></p>
1493
+ <p>Match whole word: <booleaninput name="wholeWord"/></p>
1494
+ <p>Match case: <booleaninput name="matchCase"/></p>
1495
+ <p>Replacement: <textinput name="replacement" prefill="bye"/></p>
1496
+ <p>Preserve case: <booleaninput name="preserveCase"/></p>
1497
+
1498
+ <p>Substituted: <substitute type="text" match="$match" replacement="$replacement" matchWholeWord="$wholeWord" matchCase="$matchCase" preserveCase="$preserveCase" assignNames="subbed" name="s">$orig2</substitute></p>
1499
+
1500
+ <p>Substituted 2: <textinput name="subbed2" bindValueTo="$subbed" size="20" /></p>
1501
+
1502
+ <p><copy prop="value" target="matchCase" assignNames="matchCase2" /></p>
1503
+ `,
1504
+ },
1505
+ "*",
1506
+ );
1507
+ });
1508
+
1509
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
1510
+
1511
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello there");
1512
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello there");
1513
+ cy.get(cesc("#\\/subbed")).should("have.text", "bye there");
1514
+ cy.get(cesc("#\\/subbed2_input")).should("have.value", "bye there");
1515
+
1516
+ cy.window().then(async (win) => {
1517
+ let stateVariables = await win.returnAllStateVariables1();
1518
+ expect(stateVariables["/orig"].stateValues.value).eq("hello there");
1519
+ expect(stateVariables["/orig2"].stateValues.value).eq("hello there");
1520
+ expect(stateVariables["/subbed"].stateValues.value).eq("bye there");
1521
+ expect(stateVariables["/subbed2"].stateValues.value).eq("bye there");
1522
+ });
1523
+
1524
+ cy.log("change original");
1525
+ cy.get(cesc("#\\/orig_input")).type(`{end}Hello{enter}`);
1526
+
1527
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello thereHello");
1528
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello thereHello");
1529
+ cy.get(cesc("#\\/subbed")).should("have.text", "bye therebye");
1530
+ cy.get(cesc("#\\/subbed2_input")).should("have.value", "bye therebye");
1531
+
1532
+ cy.window().then(async (win) => {
1533
+ let stateVariables = await win.returnAllStateVariables1();
1534
+ expect(stateVariables["/orig"].stateValues.value).eq("hello thereHello");
1535
+ expect(stateVariables["/orig2"].stateValues.value).eq("hello thereHello");
1536
+ expect(stateVariables["/subbed"].stateValues.value).eq("bye therebye");
1537
+ expect(stateVariables["/subbed2"].stateValues.value).eq("bye therebye");
1538
+ });
1539
+
1540
+ cy.log("change subbed");
1541
+ cy.get(cesc("#\\/subbed2_input")).type(`{end}Bye{enter}`);
1542
+
1543
+ cy.get(cesc("#\\/orig_input")).should(
1544
+ "have.value",
1545
+ "hello therehellohello",
1546
+ );
1547
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello therehellohello");
1548
+ cy.get(cesc("#\\/subbed")).should("have.text", "bye therebyebye");
1549
+ cy.get(cesc("#\\/subbed2_input")).should("have.value", "bye therebyebye");
1550
+
1551
+ cy.window().then(async (win) => {
1552
+ let stateVariables = await win.returnAllStateVariables1();
1553
+ expect(stateVariables["/orig"].stateValues.value).eq(
1554
+ "hello therehellohello",
1555
+ );
1556
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1557
+ "hello therehellohello",
1558
+ );
1559
+ expect(stateVariables["/subbed"].stateValues.value).eq("bye therebyebye");
1560
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1561
+ "bye therebyebye",
1562
+ );
1563
+ });
1564
+
1565
+ cy.log("change replacement so that it is in original");
1566
+ cy.get(cesc("#\\/replacement_input")).clear().type(`There{enter}`);
1567
+
1568
+ cy.get(cesc("#\\/subbed2_input")).should(
1569
+ "have.value",
1570
+ "There thereThereThere",
1571
+ );
1572
+ cy.get(cesc("#\\/orig_input")).should(
1573
+ "have.value",
1574
+ "hello therehellohello",
1575
+ );
1576
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello therehellohello");
1577
+ cy.get(cesc("#\\/subbed")).should("have.text", "There thereThereThere");
1578
+
1579
+ cy.window().then(async (win) => {
1580
+ let stateVariables = await win.returnAllStateVariables1();
1581
+ expect(stateVariables["/orig"].stateValues.value).eq(
1582
+ "hello therehellohello",
1583
+ );
1584
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1585
+ "hello therehellohello",
1586
+ );
1587
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1588
+ "There thereThereThere",
1589
+ );
1590
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1591
+ "There thereThereThere",
1592
+ );
1593
+ });
1594
+
1595
+ cy.log("Cannot modify subbed");
1596
+ cy.get(cesc("#\\/subbed2_input")).type(`{end} extra{enter}`);
1597
+
1598
+ cy.get(cesc("#\\/subbed2_input")).should(
1599
+ "have.value",
1600
+ "There thereThereThere",
1601
+ );
1602
+ cy.get(cesc("#\\/orig_input")).should(
1603
+ "have.value",
1604
+ "hello therehellohello",
1605
+ );
1606
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello therehellohello");
1607
+ cy.get(cesc("#\\/subbed")).should("have.text", "There thereThereThere");
1608
+
1609
+ cy.window().then(async (win) => {
1610
+ let stateVariables = await win.returnAllStateVariables1();
1611
+ expect(stateVariables["/orig"].stateValues.value).eq(
1612
+ "hello therehellohello",
1613
+ );
1614
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1615
+ "hello therehellohello",
1616
+ );
1617
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1618
+ "There thereThereThere",
1619
+ );
1620
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1621
+ "There thereThereThere",
1622
+ );
1623
+ });
1624
+
1625
+ cy.log("change original to not contain replacement");
1626
+ cy.get(cesc("#\\/orig_input")).type(
1627
+ "{end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}n{enter}",
1628
+ );
1629
+
1630
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhellohello");
1631
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello thenhellohello");
1632
+ cy.get(cesc("#\\/subbed")).should("have.text", "There thenThereThere");
1633
+ cy.get(cesc("#\\/subbed2_input")).should(
1634
+ "have.value",
1635
+ "There thenThereThere",
1636
+ );
1637
+
1638
+ cy.window().then(async (win) => {
1639
+ let stateVariables = await win.returnAllStateVariables1();
1640
+ expect(stateVariables["/orig"].stateValues.value).eq(
1641
+ "hello thenhellohello",
1642
+ );
1643
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1644
+ "hello thenhellohello",
1645
+ );
1646
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1647
+ "There thenThereThere",
1648
+ );
1649
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1650
+ "There thenThereThere",
1651
+ );
1652
+ });
1653
+
1654
+ cy.log("Can modify subbed again");
1655
+ cy.get(cesc("#\\/subbed2_input")).type(
1656
+ `{end}{backspace}{backspace}{enter}`,
1657
+ );
1658
+
1659
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello thenhelloThe");
1660
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThe");
1661
+ cy.get(cesc("#\\/subbed")).should("have.text", "There thenThereThe");
1662
+ cy.get(cesc("#\\/subbed2_input")).should(
1663
+ "have.value",
1664
+ "There thenThereThe",
1665
+ );
1666
+
1667
+ cy.window().then(async (win) => {
1668
+ let stateVariables = await win.returnAllStateVariables1();
1669
+ expect(stateVariables["/orig"].stateValues.value).eq(
1670
+ "hello thenhelloThe",
1671
+ );
1672
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1673
+ "hello thenhelloThe",
1674
+ );
1675
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1676
+ "There thenThereThe",
1677
+ );
1678
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1679
+ "There thenThereThe",
1680
+ );
1681
+ });
1682
+
1683
+ cy.log("Cannot modify subbed to include match");
1684
+ cy.get(cesc("#\\/subbed2_input")).type(`{end}HELLO{enter}`);
1685
+
1686
+ cy.get(cesc("#\\/subbed2_input")).should(
1687
+ "have.value",
1688
+ "There thenThereThe",
1689
+ );
1690
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello thenhelloThe");
1691
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThe");
1692
+ cy.get(cesc("#\\/subbed")).should("have.text", "There thenThereThe");
1693
+
1694
+ cy.window().then(async (win) => {
1695
+ let stateVariables = await win.returnAllStateVariables1();
1696
+ expect(stateVariables["/orig"].stateValues.value).eq(
1697
+ "hello thenhelloThe",
1698
+ );
1699
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1700
+ "hello thenhelloThe",
1701
+ );
1702
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1703
+ "There thenThereThe",
1704
+ );
1705
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1706
+ "There thenThereThe",
1707
+ );
1708
+ });
1709
+
1710
+ cy.log("match whole word");
1711
+ cy.get(cesc("#\\/wholeWord")).click();
1712
+
1713
+ cy.get(cesc("#\\/subbed2_input")).should(
1714
+ "have.value",
1715
+ "There thenhelloThe",
1716
+ );
1717
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello thenhelloThe");
1718
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThe");
1719
+ cy.get(cesc("#\\/subbed")).should("have.text", "There thenhelloThe");
1720
+
1721
+ cy.window().then(async (win) => {
1722
+ let stateVariables = await win.returnAllStateVariables1();
1723
+ expect(stateVariables["/orig"].stateValues.value).eq(
1724
+ "hello thenhelloThe",
1725
+ );
1726
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1727
+ "hello thenhelloThe",
1728
+ );
1729
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1730
+ "There thenhelloThe",
1731
+ );
1732
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1733
+ "There thenhelloThe",
1734
+ );
1735
+ });
1736
+
1737
+ cy.log("change replacement so matches original, but not as a whole word");
1738
+ cy.get(cesc("#\\/replacement_input")).clear().type(`Then{enter}`);
1739
+
1740
+ cy.get(cesc("#\\/subbed2_input")).should("have.value", "Then thenhelloThe");
1741
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello thenhelloThe");
1742
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThe");
1743
+ cy.get(cesc("#\\/subbed")).should("have.text", "Then thenhelloThe");
1744
+
1745
+ cy.window().then(async (win) => {
1746
+ let stateVariables = await win.returnAllStateVariables1();
1747
+ expect(stateVariables["/orig"].stateValues.value).eq(
1748
+ "hello thenhelloThe",
1749
+ );
1750
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1751
+ "hello thenhelloThe",
1752
+ );
1753
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1754
+ "Then thenhelloThe",
1755
+ );
1756
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1757
+ "Then thenhelloThe",
1758
+ );
1759
+ });
1760
+
1761
+ cy.log("Can still modify subbed");
1762
+ cy.get(cesc("#\\/subbed2_input")).type(`{end}re{enter}`);
1763
+
1764
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello thenhelloThere");
1765
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThere");
1766
+ cy.get(cesc("#\\/subbed")).should("have.text", "Then thenhelloThere");
1767
+ cy.get(cesc("#\\/subbed2_input")).should(
1768
+ "have.value",
1769
+ "Then thenhelloThere",
1770
+ );
1771
+
1772
+ cy.window().then(async (win) => {
1773
+ let stateVariables = await win.returnAllStateVariables1();
1774
+ expect(stateVariables["/orig"].stateValues.value).eq(
1775
+ "hello thenhelloThere",
1776
+ );
1777
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1778
+ "hello thenhelloThere",
1779
+ );
1780
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1781
+ "Then thenhelloThere",
1782
+ );
1783
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1784
+ "Then thenhelloThere",
1785
+ );
1786
+ });
1787
+
1788
+ cy.log("Cannnot modify subbed by adding spaces to separate match");
1789
+ cy.get(cesc("#\\/subbed2_input")).type(
1790
+ `{end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow} {leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow} {enter}`,
1791
+ );
1792
+
1793
+ cy.get(cesc("#\\/subbed2_input")).should(
1794
+ "have.value",
1795
+ "Then thenhelloThere",
1796
+ );
1797
+ cy.get(cesc("#\\/orig_input")).should("have.value", "hello thenhelloThere");
1798
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello thenhelloThere");
1799
+ cy.get(cesc("#\\/subbed")).should("have.text", "Then thenhelloThere");
1800
+
1801
+ cy.window().then(async (win) => {
1802
+ let stateVariables = await win.returnAllStateVariables1();
1803
+ expect(stateVariables["/orig"].stateValues.value).eq(
1804
+ "hello thenhelloThere",
1805
+ );
1806
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1807
+ "hello thenhelloThere",
1808
+ );
1809
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1810
+ "Then thenhelloThere",
1811
+ );
1812
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1813
+ "Then thenhelloThere",
1814
+ );
1815
+ });
1816
+
1817
+ cy.log(
1818
+ "change original so that replacement matches original as a whole word",
1819
+ );
1820
+ cy.get(cesc("#\\/orig_input")).type(
1821
+ "{end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow} {enter}",
1822
+ );
1823
+
1824
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello then helloThere");
1825
+ cy.get(cesc("#\\/orig_input")).should(
1826
+ "have.value",
1827
+ "hello then helloThere",
1828
+ );
1829
+ cy.get(cesc("#\\/subbed")).should("have.text", "Then then helloThere");
1830
+ cy.get(cesc("#\\/subbed2_input")).should(
1831
+ "have.value",
1832
+ "Then then helloThere",
1833
+ );
1834
+
1835
+ cy.window().then(async (win) => {
1836
+ let stateVariables = await win.returnAllStateVariables1();
1837
+ expect(stateVariables["/orig"].stateValues.value).eq(
1838
+ "hello then helloThere",
1839
+ );
1840
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1841
+ "hello then helloThere",
1842
+ );
1843
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1844
+ "Then then helloThere",
1845
+ );
1846
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1847
+ "Then then helloThere",
1848
+ );
1849
+ });
1850
+
1851
+ cy.log("Cannot modify subbed due to replacement match");
1852
+ cy.get(cesc("#\\/subbed2_input")).type(`{end}nothing{enter}`);
1853
+
1854
+ cy.get(cesc("#\\/subbed2_input")).should(
1855
+ "have.value",
1856
+ "Then then helloThere",
1857
+ );
1858
+ cy.get(cesc("#\\/orig_input")).should(
1859
+ "have.value",
1860
+ "hello then helloThere",
1861
+ );
1862
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello then helloThere");
1863
+ cy.get(cesc("#\\/subbed")).should("have.text", "Then then helloThere");
1864
+
1865
+ cy.window().then(async (win) => {
1866
+ let stateVariables = await win.returnAllStateVariables1();
1867
+ expect(stateVariables["/orig"].stateValues.value).eq(
1868
+ "hello then helloThere",
1869
+ );
1870
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1871
+ "hello then helloThere",
1872
+ );
1873
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1874
+ "Then then helloThere",
1875
+ );
1876
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1877
+ "Then then helloThere",
1878
+ );
1879
+ });
1880
+
1881
+ cy.log("match case");
1882
+ cy.get(cesc("#\\/matchCase")).click();
1883
+
1884
+ cy.get(cesc("#\\/matchCase2")).should("have.text", "true");
1885
+
1886
+ cy.get(cesc("#\\/orig_input")).should(
1887
+ "have.value",
1888
+ "hello then helloThere",
1889
+ );
1890
+ cy.get(cesc("#\\/orig2")).should("have.text", "hello then helloThere");
1891
+ cy.get(cesc("#\\/subbed")).should("have.text", "Then then helloThere");
1892
+ cy.get(cesc("#\\/subbed2_input")).should(
1893
+ "have.value",
1894
+ "Then then helloThere",
1895
+ );
1896
+
1897
+ cy.window().then(async (win) => {
1898
+ let stateVariables = await win.returnAllStateVariables1();
1899
+ expect(stateVariables["/orig"].stateValues.value).eq(
1900
+ "hello then helloThere",
1901
+ );
1902
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1903
+ "hello then helloThere",
1904
+ );
1905
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1906
+ "Then then helloThere",
1907
+ );
1908
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1909
+ "Then then helloThere",
1910
+ );
1911
+ });
1912
+
1913
+ cy.log(
1914
+ "Now cannot modify subbed due to replacement not matching original case",
1915
+ );
1916
+ cy.get(cesc("#\\/subbed2_input")).type(`{end} Hello{enter}`);
1917
+
1918
+ cy.get(cesc("#\\/subbed2_input")).should(
1919
+ "have.value",
1920
+ "Then then helloThere Hello",
1921
+ );
1922
+ cy.get(cesc("#\\/orig_input")).should(
1923
+ "have.value",
1924
+ "hello then helloThere Hello",
1925
+ );
1926
+ cy.get(cesc("#\\/orig2")).should(
1927
+ "have.text",
1928
+ "hello then helloThere Hello",
1929
+ );
1930
+ cy.get(cesc("#\\/subbed")).should(
1931
+ "have.text",
1932
+ "Then then helloThere Hello",
1933
+ );
1934
+
1935
+ cy.window().then(async (win) => {
1936
+ let stateVariables = await win.returnAllStateVariables1();
1937
+ expect(stateVariables["/orig"].stateValues.value).eq(
1938
+ "hello then helloThere Hello",
1939
+ );
1940
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1941
+ "hello then helloThere Hello",
1942
+ );
1943
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1944
+ "Then then helloThere Hello",
1945
+ );
1946
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1947
+ "Then then helloThere Hello",
1948
+ );
1949
+ });
1950
+
1951
+ cy.log("Cannot add match to subbed");
1952
+ cy.get(cesc("#\\/subbed2_input")).type(`{end} hello{enter}`);
1953
+
1954
+ cy.get(cesc("#\\/subbed2_input")).should(
1955
+ "have.value",
1956
+ "Then then helloThere Hello",
1957
+ );
1958
+ cy.get(cesc("#\\/orig_input")).should(
1959
+ "have.value",
1960
+ "hello then helloThere Hello",
1961
+ );
1962
+ cy.get(cesc("#\\/orig2")).should(
1963
+ "have.text",
1964
+ "hello then helloThere Hello",
1965
+ );
1966
+ cy.get(cesc("#\\/subbed")).should(
1967
+ "have.text",
1968
+ "Then then helloThere Hello",
1969
+ );
1970
+
1971
+ cy.window().then(async (win) => {
1972
+ let stateVariables = await win.returnAllStateVariables1();
1973
+ expect(stateVariables["/orig"].stateValues.value).eq(
1974
+ "hello then helloThere Hello",
1975
+ );
1976
+ expect(stateVariables["/orig2"].stateValues.value).eq(
1977
+ "hello then helloThere Hello",
1978
+ );
1979
+ expect(stateVariables["/subbed"].stateValues.value).eq(
1980
+ "Then then helloThere Hello",
1981
+ );
1982
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
1983
+ "Then then helloThere Hello",
1984
+ );
1985
+ });
1986
+
1987
+ cy.log("Change subbed to switch cases");
1988
+ cy.get(cesc("#\\/subbed2_input")).type(
1989
+ `{home}{rightArrow}{backspace}t{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}T{enter}`,
1990
+ );
1991
+
1992
+ cy.get(cesc("#\\/orig_input")).should(
1993
+ "have.value",
1994
+ "then hello helloThere Hello",
1995
+ );
1996
+ cy.get(cesc("#\\/orig2")).should(
1997
+ "have.text",
1998
+ "then hello helloThere Hello",
1999
+ );
2000
+ cy.get(cesc("#\\/subbed")).should(
2001
+ "have.text",
2002
+ "then Then helloThere Hello",
2003
+ );
2004
+ cy.get(cesc("#\\/subbed2_input")).should(
2005
+ "have.value",
2006
+ "then Then helloThere Hello",
2007
+ );
2008
+
2009
+ cy.window().then(async (win) => {
2010
+ let stateVariables = await win.returnAllStateVariables1();
2011
+ expect(stateVariables["/orig"].stateValues.value).eq(
2012
+ "then hello helloThere Hello",
2013
+ );
2014
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2015
+ "then hello helloThere Hello",
2016
+ );
2017
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2018
+ "then Then helloThere Hello",
2019
+ );
2020
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2021
+ "then Then helloThere Hello",
2022
+ );
2023
+ });
2024
+
2025
+ cy.log("preserve case");
2026
+ cy.get(cesc("#\\/preserveCase")).click();
2027
+
2028
+ cy.get(cesc("#\\/subbed2_input")).should(
2029
+ "have.value",
2030
+ "then then helloThere Hello",
2031
+ );
2032
+ cy.get(cesc("#\\/orig_input")).should(
2033
+ "have.value",
2034
+ "then hello helloThere Hello",
2035
+ );
2036
+ cy.get(cesc("#\\/orig2")).should(
2037
+ "have.text",
2038
+ "then hello helloThere Hello",
2039
+ );
2040
+ cy.get(cesc("#\\/subbed")).should(
2041
+ "have.text",
2042
+ "then then helloThere Hello",
2043
+ );
2044
+
2045
+ cy.window().then(async (win) => {
2046
+ let stateVariables = await win.returnAllStateVariables1();
2047
+ expect(stateVariables["/orig"].stateValues.value).eq(
2048
+ "then hello helloThere Hello",
2049
+ );
2050
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2051
+ "then hello helloThere Hello",
2052
+ );
2053
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2054
+ "then then helloThere Hello",
2055
+ );
2056
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2057
+ "then then helloThere Hello",
2058
+ );
2059
+ });
2060
+
2061
+ cy.log(
2062
+ "Cannot change subbed since original contains effective replacement",
2063
+ );
2064
+ cy.get(cesc("#\\/subbed2_input")).type(`{end} more{enter}`);
2065
+
2066
+ cy.get(cesc("#\\/subbed2_input")).should(
2067
+ "have.value",
2068
+ "then then helloThere Hello",
2069
+ );
2070
+ cy.get(cesc("#\\/orig_input")).should(
2071
+ "have.value",
2072
+ "then hello helloThere Hello",
2073
+ );
2074
+ cy.get(cesc("#\\/orig2")).should(
2075
+ "have.text",
2076
+ "then hello helloThere Hello",
2077
+ );
2078
+ cy.get(cesc("#\\/subbed")).should(
2079
+ "have.text",
2080
+ "then then helloThere Hello",
2081
+ );
2082
+
2083
+ cy.window().then(async (win) => {
2084
+ let stateVariables = await win.returnAllStateVariables1();
2085
+ expect(stateVariables["/orig"].stateValues.value).eq(
2086
+ "then hello helloThere Hello",
2087
+ );
2088
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2089
+ "then hello helloThere Hello",
2090
+ );
2091
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2092
+ "then then helloThere Hello",
2093
+ );
2094
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2095
+ "then then helloThere Hello",
2096
+ );
2097
+ });
2098
+
2099
+ cy.log(
2100
+ "change case of match so that effective replacement is not in original",
2101
+ );
2102
+ cy.get(cesc("#\\/match_input")).type(
2103
+ `{home}{rightArrow}{backspace}H{enter}`,
2104
+ );
2105
+
2106
+ cy.get(cesc("#\\/subbed2_input")).should(
2107
+ "have.value",
2108
+ "then hello helloThere Then",
2109
+ );
2110
+ cy.get(cesc("#\\/orig_input")).should(
2111
+ "have.value",
2112
+ "then hello helloThere Hello",
2113
+ );
2114
+ cy.get(cesc("#\\/orig2")).should(
2115
+ "have.text",
2116
+ "then hello helloThere Hello",
2117
+ );
2118
+ cy.get(cesc("#\\/subbed")).should(
2119
+ "have.text",
2120
+ "then hello helloThere Then",
2121
+ );
2122
+
2123
+ cy.window().then(async (win) => {
2124
+ let stateVariables = await win.returnAllStateVariables1();
2125
+ expect(stateVariables["/orig"].stateValues.value).eq(
2126
+ "then hello helloThere Hello",
2127
+ );
2128
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2129
+ "then hello helloThere Hello",
2130
+ );
2131
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2132
+ "then hello helloThere Then",
2133
+ );
2134
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2135
+ "then hello helloThere Then",
2136
+ );
2137
+ });
2138
+
2139
+ cy.log("Can now change subbed");
2140
+ cy.get(cesc("#\\/subbed2_input")).type(
2141
+ `{home}{rightArrow}{backspace}T{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}{backspace}{backspace}{backspace}{backspace}HELLO THEN{enter}`,
2142
+ );
2143
+
2144
+ cy.get(cesc("#\\/orig_input")).should(
2145
+ "have.value",
2146
+ "Hello HELLO THEN helloThere Hello",
2147
+ );
2148
+ cy.get(cesc("#\\/orig2")).should(
2149
+ "have.text",
2150
+ "Hello HELLO THEN helloThere Hello",
2151
+ );
2152
+ cy.get(cesc("#\\/subbed")).should(
2153
+ "have.text",
2154
+ "Then HELLO THEN helloThere Then",
2155
+ );
2156
+ cy.get(cesc("#\\/subbed2_input")).should(
2157
+ "have.value",
2158
+ "Then HELLO THEN helloThere Then",
2159
+ );
2160
+
2161
+ cy.window().then(async (win) => {
2162
+ let stateVariables = await win.returnAllStateVariables1();
2163
+ expect(stateVariables["/orig"].stateValues.value).eq(
2164
+ "Hello HELLO THEN helloThere Hello",
2165
+ );
2166
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2167
+ "Hello HELLO THEN helloThere Hello",
2168
+ );
2169
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2170
+ "Then HELLO THEN helloThere Then",
2171
+ );
2172
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2173
+ "Then HELLO THEN helloThere Then",
2174
+ );
2175
+ });
2176
+
2177
+ cy.log(
2178
+ "change case of match so that effective replacement is again in original",
2179
+ );
2180
+ cy.get(cesc("#\\/match_input")).type(
2181
+ `{home}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}{backspace}{backspace}{backspace}ELLO{enter}`,
2182
+ );
2183
+
2184
+ cy.get(cesc("#\\/subbed2_input")).should(
2185
+ "have.value",
2186
+ "Hello THEN THEN helloThere Hello",
2187
+ );
2188
+ cy.get(cesc("#\\/orig_input")).should(
2189
+ "have.value",
2190
+ "Hello HELLO THEN helloThere Hello",
2191
+ );
2192
+ cy.get(cesc("#\\/orig2")).should(
2193
+ "have.text",
2194
+ "Hello HELLO THEN helloThere Hello",
2195
+ );
2196
+ cy.get(cesc("#\\/subbed")).should(
2197
+ "have.text",
2198
+ "Hello THEN THEN helloThere Hello",
2199
+ );
2200
+
2201
+ cy.window().then(async (win) => {
2202
+ let stateVariables = await win.returnAllStateVariables1();
2203
+ expect(stateVariables["/orig"].stateValues.value).eq(
2204
+ "Hello HELLO THEN helloThere Hello",
2205
+ );
2206
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2207
+ "Hello HELLO THEN helloThere Hello",
2208
+ );
2209
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2210
+ "Hello THEN THEN helloThere Hello",
2211
+ );
2212
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2213
+ "Hello THEN THEN helloThere Hello",
2214
+ );
2215
+ });
2216
+
2217
+ cy.log("Cannot change subbed");
2218
+ cy.get(cesc("#\\/subbed2_input")).type(`{end} ineffective{enter}`);
2219
+
2220
+ cy.get(cesc("#\\/subbed2_input")).should(
2221
+ "have.value",
2222
+ "Hello THEN THEN helloThere Hello",
2223
+ );
2224
+ cy.get(cesc("#\\/orig_input")).should(
2225
+ "have.value",
2226
+ "Hello HELLO THEN helloThere Hello",
2227
+ );
2228
+ cy.get(cesc("#\\/orig2")).should(
2229
+ "have.text",
2230
+ "Hello HELLO THEN helloThere Hello",
2231
+ );
2232
+ cy.get(cesc("#\\/subbed")).should(
2233
+ "have.text",
2234
+ "Hello THEN THEN helloThere Hello",
2235
+ );
2236
+
2237
+ cy.window().then(async (win) => {
2238
+ let stateVariables = await win.returnAllStateVariables1();
2239
+ expect(stateVariables["/orig"].stateValues.value).eq(
2240
+ "Hello HELLO THEN helloThere Hello",
2241
+ );
2242
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2243
+ "Hello HELLO THEN helloThere Hello",
2244
+ );
2245
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2246
+ "Hello THEN THEN helloThere Hello",
2247
+ );
2248
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2249
+ "Hello THEN THEN helloThere Hello",
2250
+ );
2251
+ });
2252
+
2253
+ cy.log("change original so no longer has effective replacement");
2254
+ cy.get(cesc("#\\/orig_input")).type(
2255
+ `{home}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{rightArrow}{backspace}{backspace}{backspace}hen{enter}`,
2256
+ );
2257
+
2258
+ cy.get(cesc("#\\/orig2")).should(
2259
+ "have.text",
2260
+ "Hello HELLO Then helloThere Hello",
2261
+ );
2262
+ cy.get(cesc("#\\/orig_input")).should(
2263
+ "have.value",
2264
+ "Hello HELLO Then helloThere Hello",
2265
+ );
2266
+ cy.get(cesc("#\\/subbed")).should(
2267
+ "have.text",
2268
+ "Hello THEN Then helloThere Hello",
2269
+ );
2270
+ cy.get(cesc("#\\/subbed2_input")).should(
2271
+ "have.value",
2272
+ "Hello THEN Then helloThere Hello",
2273
+ );
2274
+
2275
+ cy.window().then(async (win) => {
2276
+ let stateVariables = await win.returnAllStateVariables1();
2277
+ expect(stateVariables["/orig"].stateValues.value).eq(
2278
+ "Hello HELLO Then helloThere Hello",
2279
+ );
2280
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2281
+ "Hello HELLO Then helloThere Hello",
2282
+ );
2283
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2284
+ "Hello THEN Then helloThere Hello",
2285
+ );
2286
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2287
+ "Hello THEN Then helloThere Hello",
2288
+ );
2289
+ });
2290
+
2291
+ cy.log("Can change subbed once more");
2292
+ cy.get(cesc("#\\/subbed2_input")).type(
2293
+ `{end}{backspace}{backspace}{backspace}{backspace}{backspace}THEN{enter}`,
2294
+ );
2295
+
2296
+ cy.get(cesc("#\\/orig_input")).should(
2297
+ "have.value",
2298
+ "Hello HELLO Then helloThere HELLO",
2299
+ );
2300
+ cy.get(cesc("#\\/orig2")).should(
2301
+ "have.text",
2302
+ "Hello HELLO Then helloThere HELLO",
2303
+ );
2304
+ cy.get(cesc("#\\/subbed")).should(
2305
+ "have.text",
2306
+ "Hello THEN Then helloThere THEN",
2307
+ );
2308
+ cy.get(cesc("#\\/subbed2_input")).should(
2309
+ "have.value",
2310
+ "Hello THEN Then helloThere THEN",
2311
+ );
2312
+
2313
+ cy.window().then(async (win) => {
2314
+ let stateVariables = await win.returnAllStateVariables1();
2315
+ expect(stateVariables["/orig"].stateValues.value).eq(
2316
+ "Hello HELLO Then helloThere HELLO",
2317
+ );
2318
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2319
+ "Hello HELLO Then helloThere HELLO",
2320
+ );
2321
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2322
+ "Hello THEN Then helloThere THEN",
2323
+ );
2324
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2325
+ "Hello THEN Then helloThere THEN",
2326
+ );
2327
+ });
2328
+
2329
+ cy.log("Cannot add match to subbed");
2330
+ cy.get(cesc("#\\/subbed2_input")).type(`{end} HELLO{enter}`);
2331
+
2332
+ cy.get(cesc("#\\/subbed2_input")).should(
2333
+ "have.value",
2334
+ "Hello THEN Then helloThere THEN",
2335
+ );
2336
+ cy.get(cesc("#\\/orig_input")).should(
2337
+ "have.value",
2338
+ "Hello HELLO Then helloThere HELLO",
2339
+ );
2340
+ cy.get(cesc("#\\/orig2")).should(
2341
+ "have.text",
2342
+ "Hello HELLO Then helloThere HELLO",
2343
+ );
2344
+ cy.get(cesc("#\\/subbed")).should(
2345
+ "have.text",
2346
+ "Hello THEN Then helloThere THEN",
2347
+ );
2348
+
2349
+ cy.window().then(async (win) => {
2350
+ let stateVariables = await win.returnAllStateVariables1();
2351
+ expect(stateVariables["/orig"].stateValues.value).eq(
2352
+ "Hello HELLO Then helloThere HELLO",
2353
+ );
2354
+ expect(stateVariables["/orig2"].stateValues.value).eq(
2355
+ "Hello HELLO Then helloThere HELLO",
2356
+ );
2357
+ expect(stateVariables["/subbed"].stateValues.value).eq(
2358
+ "Hello THEN Then helloThere THEN",
2359
+ );
2360
+ expect(stateVariables["/subbed2"].stateValues.value).eq(
2361
+ "Hello THEN Then helloThere THEN",
2362
+ );
2363
+ });
2364
+ });
2365
+
2366
+ it("substitute with incomplete attributes does nothing", () => {
2367
+ cy.window().then(async (win) => {
2368
+ win.postMessage(
2369
+ {
2370
+ doenetML: `
2371
+ <text>a</text>
2372
+ <substitute assignNames="m1">x+1</substitute>
2373
+ <substitute assignNames="m2" match="x">x+1</substitute>
2374
+ <substitute assignNames="m3" replacement="y">x+1</substitute>
2375
+ <substitute type="text" assignNames="t1">hello</substitute>
2376
+ <substitute type="text" assignNames="t2" match="hello">hello</substitute>
2377
+ <substitute type="text" assignNames="t3" replacement="bye">hello</substitute>
2378
+ `,
2379
+ },
2380
+ "*",
2381
+ );
2382
+ });
2383
+
2384
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
2385
+
2386
+ cy.get(cesc("#\\/m1") + " .mjx-mrow")
2387
+ .eq(0)
2388
+ .invoke("text")
2389
+ .then((text) => {
2390
+ expect(text.trim()).equal("x+1");
2391
+ });
2392
+ cy.get(cesc("#\\/m2") + " .mjx-mrow")
2393
+ .eq(0)
2394
+ .invoke("text")
2395
+ .then((text) => {
2396
+ expect(text.trim()).equal("x+1");
2397
+ });
2398
+ cy.get(cesc("#\\/m3") + " .mjx-mrow")
2399
+ .eq(0)
2400
+ .invoke("text")
2401
+ .then((text) => {
2402
+ expect(text.trim()).equal("x+1");
2403
+ });
2404
+
2405
+ cy.get(cesc("#\\/t1")).should("have.text", "hello");
2406
+ cy.get(cesc("#\\/t2")).should("have.text", "hello");
2407
+ cy.get(cesc("#\\/t3")).should("have.text", "hello");
2408
+ });
2409
+
2410
+ it("rounding with math", () => {
2411
+ cy.window().then(async (win) => {
2412
+ win.postMessage(
2413
+ {
2414
+ doenetML: `
2415
+ <text>a</text>
2416
+ <math name="orig">ax+847.29418392+5y</math>
2417
+ <math name="origDig3" displayDigits="3" ignoreDisplayDecimals>ax+847.29418392+5y</math>
2418
+ <math name="origDec3" displayDecimals="3" ignoreDisplayDigits>ax+847.29418392+5y</math>
2419
+ <math name="origPad" padZeros>ax+847.29418392+5y</math>
2420
+
2421
+ <p><substitute match="a" replacement="0.07394918" assignNames="e1">
2422
+ $orig
2423
+ </substitute>
2424
+ <substitute match="a" replacement="0.07394918" assignNames="e1Dig4" displayDigits="4" ignoreDisplayDecimals>
2425
+ $orig
2426
+ </substitute>
2427
+ <substitute match="a" replacement="0.07394918" assignNames="e1Dec4" displayDecimals="4" ignoreDisplayDigits>
2428
+ $orig
2429
+ </substitute>
2430
+ <substitute match="a" replacement="0.07394918" assignNames="e1Pad" padZeros>
2431
+ $orig
2432
+ </substitute></p>
2433
+ <p>
2434
+ <math copySource="e1Dec4" name="e1Dig4a" displayDigits="4" ignoreDisplayDecimals />
2435
+ <math copySource="e1Dig4" name="e1Dec4a" displayDecimals="4" ignoreDisplayDigits />
2436
+ </p>
2437
+
2438
+
2439
+ <p><substitute match="a" replacement="0.07394918" assignNames="e2">
2440
+ $origDig3
2441
+ </substitute>
2442
+ <substitute match="a" replacement="0.07394918" assignNames="e2Dig4" displayDigits="4" ignoreDisplayDecimals>
2443
+ $origDig3
2444
+ </substitute>
2445
+ <substitute match="a" replacement="0.07394918" assignNames="e2Dec4" displayDecimals="4" ignoreDisplayDigits>
2446
+ $origDig3
2447
+ </substitute>
2448
+ <substitute match="a" replacement="0.07394918" assignNames="e2Pad" padZeros>
2449
+ $origDig3
2450
+ </substitute></p>
2451
+ <p>
2452
+ <math copySource="e2Dec4" name="e2Dig4a" displayDigits="4" ignoreDisplayDecimals />
2453
+ <math copySource="e2Dig4" name="e2Dec4a" displayDecimals="4" ignoreDisplayDigits />
2454
+ </p>
2455
+
2456
+ <p><substitute match="a" replacement="0.07394918" assignNames="e3">
2457
+ $origDec3
2458
+ </substitute>
2459
+ <substitute match="a" replacement="0.07394918" assignNames="e3Dig4" displayDigits="4" ignoreDisplayDecimals >
2460
+ $origDec3
2461
+ </substitute>
2462
+ <substitute match="a" replacement="0.07394918" assignNames="e3Dec4" displayDecimals="4" ignoreDisplayDigits >
2463
+ $origDec3
2464
+ </substitute>
2465
+ <substitute match="a" replacement="0.07394918" assignNames="e3Pad" padZeros>
2466
+ $origDec3
2467
+ </substitute></p>
2468
+ <p>
2469
+ <math copySource="e3Dec4" name="e3Dig4a" displayDigits="4" ignoreDisplayDecimals />
2470
+ <math copySource="e3Dig4" name="e3Dec4a" displayDecimals="4" ignoreDisplayDigits />
2471
+ </p>
2472
+
2473
+ <p><substitute match="a" replacement="0.07394918" assignNames="e4">
2474
+ $origPad
2475
+ </substitute>
2476
+ <substitute match="a" replacement="0.07394918" assignNames="e4Dig4" displayDigits="4" ignoreDisplayDecimals >
2477
+ $origPad
2478
+ </substitute>
2479
+ <substitute match="a" replacement="0.07394918" assignNames="e4Dec4" displayDecimals="4" ignoreDisplayDigits >
2480
+ $origPad
2481
+ </substitute>
2482
+ <substitute match="a" replacement="0.07394918" assignNames="e4NoPad" padZeros="false">
2483
+ $origPad
2484
+ </substitute></p>
2485
+ <p>
2486
+ <math copySource="e4Dec4" name="e4Dig4a" displayDigits="4" ignoreDisplayDecimals />
2487
+ <math copySource="e4Dig4" name="e4Dec4a" displayDecimals="4" ignoreDisplayDigits />
2488
+ </p>
2489
+
2490
+ `,
2491
+ },
2492
+ "*",
2493
+ );
2494
+ });
2495
+
2496
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
2497
+
2498
+ cy.get(cesc("#\\/e1") + " .mjx-mrow")
2499
+ .eq(0)
2500
+ .invoke("text")
2501
+ .then((text) => {
2502
+ expect(text).equal("0.0739x+847.29+5y");
2503
+ });
2504
+ cy.get(cesc("#\\/e1Dig4") + " .mjx-mrow")
2505
+ .eq(0)
2506
+ .invoke("text")
2507
+ .then((text) => {
2508
+ expect(text).equal("0.07395x+847.3+5y");
2509
+ });
2510
+ cy.get(cesc("#\\/e1Dec4") + " .mjx-mrow")
2511
+ .eq(0)
2512
+ .invoke("text")
2513
+ .then((text) => {
2514
+ expect(text).equal("0.0739x+847.2942+5y");
2515
+ });
2516
+ cy.get(cesc("#\\/e1Pad") + " .mjx-mrow")
2517
+ .eq(0)
2518
+ .invoke("text")
2519
+ .then((text) => {
2520
+ expect(text).equal("0.0739x+847.29+5.00y");
2521
+ });
2522
+ cy.get(cesc("#\\/e1Dig4a") + " .mjx-mrow")
2523
+ .eq(0)
2524
+ .invoke("text")
2525
+ .then((text) => {
2526
+ expect(text).equal("0.07395x+847.3+5y");
2527
+ });
2528
+ cy.get(cesc("#\\/e1Dec4a") + " .mjx-mrow")
2529
+ .eq(0)
2530
+ .invoke("text")
2531
+ .then((text) => {
2532
+ expect(text).equal("0.0739x+847.2942+5y");
2533
+ });
2534
+
2535
+ cy.get(cesc("#\\/e2") + " .mjx-mrow")
2536
+ .eq(0)
2537
+ .invoke("text")
2538
+ .then((text) => {
2539
+ expect(text).equal("0.0739x+847+5y");
2540
+ });
2541
+ cy.get(cesc("#\\/e2Dig4") + " .mjx-mrow")
2542
+ .eq(0)
2543
+ .invoke("text")
2544
+ .then((text) => {
2545
+ expect(text).equal("0.07395x+847.3+5y");
2546
+ });
2547
+ cy.get(cesc("#\\/e2Dec4") + " .mjx-mrow")
2548
+ .eq(0)
2549
+ .invoke("text")
2550
+ .then((text) => {
2551
+ expect(text).equal("0.0739x+847.2942+5y");
2552
+ });
2553
+ cy.get(cesc("#\\/e2Pad") + " .mjx-mrow")
2554
+ .eq(0)
2555
+ .invoke("text")
2556
+ .then((text) => {
2557
+ expect(text).equal("0.0739x+847+5.00y");
2558
+ });
2559
+ cy.get(cesc("#\\/e2Dig4a") + " .mjx-mrow")
2560
+ .eq(0)
2561
+ .invoke("text")
2562
+ .then((text) => {
2563
+ expect(text).equal("0.07395x+847.3+5y");
2564
+ });
2565
+ cy.get(cesc("#\\/e2Dec4a") + " .mjx-mrow")
2566
+ .eq(0)
2567
+ .invoke("text")
2568
+ .then((text) => {
2569
+ expect(text).equal("0.0739x+847.2942+5y");
2570
+ });
2571
+
2572
+ cy.get(cesc("#\\/e3") + " .mjx-mrow")
2573
+ .eq(0)
2574
+ .invoke("text")
2575
+ .then((text) => {
2576
+ expect(text).equal("0.074x+847.294+5y");
2577
+ });
2578
+ cy.get(cesc("#\\/e3Dig4") + " .mjx-mrow")
2579
+ .eq(0)
2580
+ .invoke("text")
2581
+ .then((text) => {
2582
+ expect(text).equal("0.07395x+847.3+5y");
2583
+ });
2584
+ cy.get(cesc("#\\/e3Dec4") + " .mjx-mrow")
2585
+ .eq(0)
2586
+ .invoke("text")
2587
+ .then((text) => {
2588
+ expect(text).equal("0.0739x+847.2942+5y");
2589
+ });
2590
+ cy.get(cesc("#\\/e3Pad") + " .mjx-mrow")
2591
+ .eq(0)
2592
+ .invoke("text")
2593
+ .then((text) => {
2594
+ expect(text).equal("0.074x+847.294+5.000y");
2595
+ });
2596
+ cy.get(cesc("#\\/e3Dig4a") + " .mjx-mrow")
2597
+ .eq(0)
2598
+ .invoke("text")
2599
+ .then((text) => {
2600
+ expect(text).equal("0.07395x+847.3+5y");
2601
+ });
2602
+ cy.get(cesc("#\\/e3Dec4a") + " .mjx-mrow")
2603
+ .eq(0)
2604
+ .invoke("text")
2605
+ .then((text) => {
2606
+ expect(text).equal("0.0739x+847.2942+5y");
2607
+ });
2608
+
2609
+ cy.get(cesc("#\\/e4") + " .mjx-mrow")
2610
+ .eq(0)
2611
+ .invoke("text")
2612
+ .then((text) => {
2613
+ expect(text).equal("0.0739x+847.29+5.00y");
2614
+ });
2615
+ cy.get(cesc("#\\/e4Dig4") + " .mjx-mrow")
2616
+ .eq(0)
2617
+ .invoke("text")
2618
+ .then((text) => {
2619
+ expect(text).equal("0.07395x+847.3+5.000y");
2620
+ });
2621
+ cy.get(cesc("#\\/e4Dec4") + " .mjx-mrow")
2622
+ .eq(0)
2623
+ .invoke("text")
2624
+ .then((text) => {
2625
+ expect(text).equal("0.0739x+847.2942+5.0000y");
2626
+ });
2627
+ cy.get(cesc("#\\/e4NoPad") + " .mjx-mrow")
2628
+ .eq(0)
2629
+ .invoke("text")
2630
+ .then((text) => {
2631
+ expect(text).equal("0.0739x+847.29+5y");
2632
+ });
2633
+ cy.get(cesc("#\\/e4Dig4a") + " .mjx-mrow")
2634
+ .eq(0)
2635
+ .invoke("text")
2636
+ .then((text) => {
2637
+ expect(text).equal("0.07395x+847.3+5.000y");
2638
+ });
2639
+ cy.get(cesc("#\\/e4Dec4a") + " .mjx-mrow")
2640
+ .eq(0)
2641
+ .invoke("text")
2642
+ .then((text) => {
2643
+ expect(text).equal("0.0739x+847.2942+5.0000y");
2644
+ });
2645
+ });
2646
+ });