@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,4047 @@
1
+ import me from "math-expressions";
2
+ import { createFunctionFromDefinition } from "../../../../src/Core/utils/function";
3
+ import { cesc, cesc2 } from "../../../../src/utils/url";
4
+
5
+ function nInDOM(n) {
6
+ if (n < 0) {
7
+ return `−${Math.abs(n)}`;
8
+ } else {
9
+ return String(n);
10
+ }
11
+ }
12
+
13
+ describe("Function Operator Tag Tests", function () {
14
+ beforeEach(() => {
15
+ cy.clearIndexedDB();
16
+ cy.visit("/src/Tools/cypressTest/");
17
+ });
18
+
19
+ it("clamp function", () => {
20
+ cy.window().then(async (win) => {
21
+ win.postMessage(
22
+ {
23
+ doenetML: `
24
+ <text>a</text>
25
+ <function name="original" symbolic="true" displayDecimals="3" ignoreDisplayDigits>x^3</function>
26
+ <clampfunction name="clamp01"><copy target="original" /></clampfunction>
27
+ <clampfunction name="clampn35" lowervalue="-3" uppervalue="5"><copy target="original" /></clampfunction>
28
+
29
+ <p><aslist>
30
+ <map>
31
+ <template newNamespace>$$(../original)($x)</template>
32
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
33
+ </map>
34
+ </aslist></p>
35
+ <p><aslist>
36
+ <map>
37
+ <template newNamespace><evaluate function="$(../clamp01)" input="$x" /></template>
38
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
39
+ </map>
40
+ </aslist></p>
41
+ <p><aslist>
42
+ <map>
43
+ <template newNamespace>$$(../clampn35)($x)</template>
44
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
45
+ </map>
46
+ </aslist></p>
47
+ <p><aslist>
48
+ <copy target="_map2" name="m4" />
49
+ </aslist></p>
50
+ <p><aslist>
51
+ <copy target="_map3" name="m5" />
52
+ </aslist></p>
53
+ `,
54
+ },
55
+ "*",
56
+ );
57
+ });
58
+
59
+ cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded
60
+
61
+ cy.window().then(async (win) => {
62
+ let stateVariables = await win.returnAllStateVariables1();
63
+ let map1Replacements = stateVariables["/_map1"].replacements.reduce(
64
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
65
+ [],
66
+ );
67
+ let map1ReplacementAnchors = map1Replacements.map((x) =>
68
+ cesc2("#" + x.componentName),
69
+ );
70
+ let map2Replacements = stateVariables["/_map2"].replacements.reduce(
71
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
72
+ [],
73
+ );
74
+ let map2ReplacementAnchors = map2Replacements.map((x) =>
75
+ cesc2("#" + x.componentName),
76
+ );
77
+ let map3Replacements = stateVariables["/_map3"].replacements.reduce(
78
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
79
+ [],
80
+ );
81
+ let map3ReplacementAnchors = map3Replacements.map((x) =>
82
+ cesc2("#" + x.componentName),
83
+ );
84
+ let map4Replacements = stateVariables["/m4"].replacements.reduce(
85
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
86
+ [],
87
+ );
88
+ let map4ReplacementAnchors = map4Replacements.map((x) =>
89
+ cesc2("#" + x.componentName),
90
+ );
91
+ let map5Replacements = stateVariables["/m5"].replacements.reduce(
92
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
93
+ [],
94
+ );
95
+ let map5ReplacementAnchors = map5Replacements.map((x) =>
96
+ cesc2("#" + x.componentName),
97
+ );
98
+
99
+ let clamp01 = (x) => Math.min(1, Math.max(0, x));
100
+ let clampn35 = (x) => Math.min(5, Math.max(-3, x));
101
+ let indToVal = (ind) => me.math.round((0.2 * (ind - 11)) ** 3, 3);
102
+
103
+ cy.log("Check values in DOM");
104
+ for (let i = 1; i <= 21; i++) {
105
+ cy.get(map1ReplacementAnchors[i - 1])
106
+ .find(".mjx-mrow")
107
+ .eq(0)
108
+ .invoke("text")
109
+ .then((text) => {
110
+ expect(text.trim().replace(/−/g, "-")).equal(
111
+ indToVal(i).toString(),
112
+ );
113
+ });
114
+
115
+ cy.get(map2ReplacementAnchors[i - 1])
116
+ .find(".mjx-mrow")
117
+ .eq(0)
118
+ .invoke("text")
119
+ .then((text) => {
120
+ expect(text.trim().replace(/−/g, "-")).equal(
121
+ clamp01(indToVal(i)).toString(),
122
+ );
123
+ });
124
+
125
+ cy.get(map3ReplacementAnchors[i - 1])
126
+ .find(".mjx-mrow")
127
+ .eq(0)
128
+ .invoke("text")
129
+ .then((text) => {
130
+ expect(text.trim().replace(/−/g, "-")).equal(
131
+ clampn35(indToVal(i)).toString(),
132
+ );
133
+ });
134
+
135
+ cy.get(map4ReplacementAnchors[i - 1])
136
+ .find(".mjx-mrow")
137
+ .eq(0)
138
+ .invoke("text")
139
+ .then((text) => {
140
+ expect(text.trim().replace(/−/g, "-")).equal(
141
+ clamp01(indToVal(i)).toString(),
142
+ );
143
+ });
144
+
145
+ cy.get(map5ReplacementAnchors[i - 1])
146
+ .find(".mjx-mrow")
147
+ .eq(0)
148
+ .invoke("text")
149
+ .then((text) => {
150
+ expect(text.trim().replace(/−/g, "-")).equal(
151
+ clampn35(indToVal(i)).toString(),
152
+ );
153
+ });
154
+ }
155
+
156
+ cy.log("check mapped state values");
157
+ cy.window().then(async (win) => {
158
+ for (let i = 1; i <= 21; i++) {
159
+ expect(
160
+ stateVariables[map1Replacements[i - 1].componentName].stateValues
161
+ .value,
162
+ ).closeTo(indToVal(i), 1e-10);
163
+ expect(
164
+ stateVariables[map2Replacements[i - 1].componentName].stateValues
165
+ .value,
166
+ ).closeTo(clamp01(indToVal(i)), 1e-10);
167
+ expect(
168
+ stateVariables[map3Replacements[i - 1].componentName].stateValues
169
+ .value,
170
+ ).closeTo(clampn35(indToVal(i)), 1e-10);
171
+ expect(
172
+ stateVariables[map4Replacements[i - 1].componentName].stateValues
173
+ .value,
174
+ ).closeTo(clamp01(indToVal(i)), 1e-10);
175
+ expect(
176
+ stateVariables[map5Replacements[i - 1].componentName].stateValues
177
+ .value,
178
+ ).closeTo(clampn35(indToVal(i)), 1e-10);
179
+ }
180
+ });
181
+
182
+ cy.log("check functions created from fDefinition");
183
+ cy.window().then(async (win) => {
184
+ let f01 = createFunctionFromDefinition(
185
+ stateVariables["/clamp01"].stateValues.fDefinitions[0],
186
+ );
187
+ let fn35 = createFunctionFromDefinition(
188
+ stateVariables["/clampn35"].stateValues.fDefinitions[0],
189
+ );
190
+
191
+ for (let i = 1; i <= 21; i++) {
192
+ let x = 0.2 * (i - 11);
193
+ expect(f01(x)).closeTo(clamp01(indToVal(i)), 1e-10);
194
+ expect(fn35(x)).closeTo(clampn35(indToVal(i)), 1e-10);
195
+ }
196
+ });
197
+ });
198
+ });
199
+
200
+ it("clamp function, numeric", () => {
201
+ cy.window().then(async (win) => {
202
+ win.postMessage(
203
+ {
204
+ doenetML: `
205
+ <text>a</text>
206
+ <function name="original" symbolic="false" displayDecimals="3" ignoreDisplayDigits>x^3</function>
207
+ <clampfunction name="clamp01"><copy target="original" /></clampfunction>
208
+ <clampfunction name="clampn35" lowervalue="-3" uppervalue="5"><copy target="original" /></clampfunction>
209
+
210
+ <p><aslist>
211
+ <map>
212
+ <template newNamespace>$$(../original)($x)</template>
213
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
214
+ </map>
215
+ </aslist></p>
216
+ <p><aslist>
217
+ <map>
218
+ <template newNamespace><evaluate function="$(../clamp01)" input="$x" /></template>
219
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
220
+ </map>
221
+ </aslist></p>
222
+ <p><aslist>
223
+ <map>
224
+ <template newNamespace>$$(../clampn35)($x)</template>
225
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
226
+ </map>
227
+ </aslist></p>
228
+ <p><aslist>
229
+ <copy target="_map2" name="m4" />
230
+ </aslist></p>
231
+ <p><aslist>
232
+ <copy target="_map3" name="m5" />
233
+ </aslist></p>
234
+ `,
235
+ },
236
+ "*",
237
+ );
238
+ });
239
+
240
+ cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded
241
+
242
+ cy.window().then(async (win) => {
243
+ let stateVariables = await win.returnAllStateVariables1();
244
+ let map1Replacements = stateVariables["/_map1"].replacements.reduce(
245
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
246
+ [],
247
+ );
248
+ let map1ReplacementAnchors = map1Replacements.map((x) =>
249
+ cesc2("#" + x.componentName),
250
+ );
251
+ let map2Replacements = stateVariables["/_map2"].replacements.reduce(
252
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
253
+ [],
254
+ );
255
+ let map2ReplacementAnchors = map2Replacements.map((x) =>
256
+ cesc2("#" + x.componentName),
257
+ );
258
+ let map3Replacements = stateVariables["/_map3"].replacements.reduce(
259
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
260
+ [],
261
+ );
262
+ let map3ReplacementAnchors = map3Replacements.map((x) =>
263
+ cesc2("#" + x.componentName),
264
+ );
265
+ let map4Replacements = stateVariables["/m4"].replacements.reduce(
266
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
267
+ [],
268
+ );
269
+ let map4ReplacementAnchors = map4Replacements.map((x) =>
270
+ cesc2("#" + x.componentName),
271
+ );
272
+ let map5Replacements = stateVariables["/m5"].replacements.reduce(
273
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
274
+ [],
275
+ );
276
+ let map5ReplacementAnchors = map5Replacements.map((x) =>
277
+ cesc2("#" + x.componentName),
278
+ );
279
+
280
+ let clamp01 = (x) => Math.min(1, Math.max(0, x));
281
+ let clampn35 = (x) => Math.min(5, Math.max(-3, x));
282
+ let indToVal = (ind) => me.math.round((0.2 * (ind - 11)) ** 3, 3);
283
+
284
+ cy.log("Check values in DOM");
285
+ for (let i = 1; i <= 21; i++) {
286
+ cy.get(map1ReplacementAnchors[i - 1])
287
+ .find(".mjx-mrow")
288
+ .eq(0)
289
+ .invoke("text")
290
+ .then((text) => {
291
+ expect(text.trim().replace(/−/g, "-")).equal(
292
+ indToVal(i).toString(),
293
+ );
294
+ });
295
+
296
+ cy.get(map2ReplacementAnchors[i - 1])
297
+ .find(".mjx-mrow")
298
+ .eq(0)
299
+ .invoke("text")
300
+ .then((text) => {
301
+ expect(text.trim().replace(/−/g, "-")).equal(
302
+ clamp01(indToVal(i)).toString(),
303
+ );
304
+ });
305
+
306
+ cy.get(map3ReplacementAnchors[i - 1])
307
+ .find(".mjx-mrow")
308
+ .eq(0)
309
+ .invoke("text")
310
+ .then((text) => {
311
+ expect(text.trim().replace(/−/g, "-")).equal(
312
+ clampn35(indToVal(i)).toString(),
313
+ );
314
+ });
315
+
316
+ cy.get(map4ReplacementAnchors[i - 1])
317
+ .find(".mjx-mrow")
318
+ .eq(0)
319
+ .invoke("text")
320
+ .then((text) => {
321
+ expect(text.trim().replace(/−/g, "-")).equal(
322
+ clamp01(indToVal(i)).toString(),
323
+ );
324
+ });
325
+
326
+ cy.get(map5ReplacementAnchors[i - 1])
327
+ .find(".mjx-mrow")
328
+ .eq(0)
329
+ .invoke("text")
330
+ .then((text) => {
331
+ expect(text.trim().replace(/−/g, "-")).equal(
332
+ clampn35(indToVal(i)).toString(),
333
+ );
334
+ });
335
+ }
336
+
337
+ cy.log("check mapped state values");
338
+ cy.window().then(async (win) => {
339
+ for (let i = 1; i <= 21; i++) {
340
+ expect(
341
+ stateVariables[map1Replacements[i - 1].componentName].stateValues
342
+ .value,
343
+ ).closeTo(indToVal(i), 1e-10);
344
+ expect(
345
+ stateVariables[map2Replacements[i - 1].componentName].stateValues
346
+ .value,
347
+ ).closeTo(clamp01(indToVal(i)), 1e-10);
348
+ expect(
349
+ stateVariables[map3Replacements[i - 1].componentName].stateValues
350
+ .value,
351
+ ).closeTo(clampn35(indToVal(i)), 1e-10);
352
+ expect(
353
+ stateVariables[map4Replacements[i - 1].componentName].stateValues
354
+ .value,
355
+ ).closeTo(clamp01(indToVal(i)), 1e-10);
356
+ expect(
357
+ stateVariables[map5Replacements[i - 1].componentName].stateValues
358
+ .value,
359
+ ).closeTo(clampn35(indToVal(i)), 1e-10);
360
+ }
361
+ });
362
+
363
+ cy.log("check functions created from fDefinition");
364
+ cy.window().then(async (win) => {
365
+ let f01 = createFunctionFromDefinition(
366
+ stateVariables["/clamp01"].stateValues.fDefinitions[0],
367
+ );
368
+ let fn35 = createFunctionFromDefinition(
369
+ stateVariables["/clampn35"].stateValues.fDefinitions[0],
370
+ );
371
+
372
+ for (let i = 1; i <= 21; i++) {
373
+ let x = 0.2 * (i - 11);
374
+ expect(f01(x)).closeTo(clamp01(indToVal(i)), 1e-10);
375
+ expect(fn35(x)).closeTo(clampn35(indToVal(i)), 1e-10);
376
+ }
377
+ });
378
+ });
379
+ });
380
+
381
+ it("clamp function, labeled", () => {
382
+ cy.window().then(async (win) => {
383
+ win.postMessage(
384
+ {
385
+ doenetML: `
386
+ <text>a</text>
387
+ <function name="original" displayDecimals="3" ignoreDisplayDigits>x^3<label>orig</label></function>
388
+ <clampfunction name="clamp01"><copy target="original" /><label>clamp 1</label></clampfunction>
389
+ <clampfunction name="clampn35" lowervalue="-3" uppervalue="5"><copy target="original" /><label>clamp 2</label></clampfunction>
390
+
391
+ <p><aslist>
392
+ <map>
393
+ <template newNamespace>$$(../original)($x)</template>
394
+ <sources alias="x"><sequence step="1" from="-2" to="2" /></sources>
395
+ </map>
396
+ </aslist></p>
397
+ <p><aslist>
398
+ <map>
399
+ <template newNamespace><evaluate function="$(../clamp01)" input="$x" /></template>
400
+ <sources alias="x"><sequence step="1" from="-2" to="2" /></sources>
401
+ </map>
402
+ </aslist></p>
403
+ <p><aslist>
404
+ <map>
405
+ <template newNamespace>$$(../clampn35)($x)</template>
406
+ <sources alias="x"><sequence step="1" from="-2" to="2" /></sources>
407
+ </map>
408
+ </aslist></p>
409
+ `,
410
+ },
411
+ "*",
412
+ );
413
+ });
414
+
415
+ cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded
416
+
417
+ cy.window().then(async (win) => {
418
+ let stateVariables = await win.returnAllStateVariables1();
419
+
420
+ expect(stateVariables["/original"].stateValues.label).eq("orig");
421
+ expect(stateVariables["/clamp01"].stateValues.label).eq("clamp 1");
422
+ expect(stateVariables["/clampn35"].stateValues.label).eq("clamp 2");
423
+
424
+ let map1Replacements = stateVariables["/_map1"].replacements.reduce(
425
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
426
+ [],
427
+ );
428
+ let map1ReplacementAnchors = map1Replacements.map((x) =>
429
+ cesc2("#" + x.componentName),
430
+ );
431
+ let map2Replacements = stateVariables["/_map2"].replacements.reduce(
432
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
433
+ [],
434
+ );
435
+ let map2ReplacementAnchors = map2Replacements.map((x) =>
436
+ cesc2("#" + x.componentName),
437
+ );
438
+ let map3Replacements = stateVariables["/_map3"].replacements.reduce(
439
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
440
+ [],
441
+ );
442
+ let map3ReplacementAnchors = map3Replacements.map((x) =>
443
+ cesc2("#" + x.componentName),
444
+ );
445
+
446
+ let clamp01 = (x) => Math.min(1, Math.max(0, x));
447
+ let clampn35 = (x) => Math.min(5, Math.max(-3, x));
448
+ let indToVal = (ind) => me.math.round((ind - 3) ** 3, 3);
449
+
450
+ cy.log("Check values in DOM");
451
+ for (let i = 1; i <= 5; i++) {
452
+ cy.get(map1ReplacementAnchors[i - 1])
453
+ .find(".mjx-mrow")
454
+ .eq(0)
455
+ .invoke("text")
456
+ .then((text) => {
457
+ expect(text.trim().replace(/−/g, "-")).equal(
458
+ indToVal(i).toString(),
459
+ );
460
+ });
461
+
462
+ cy.get(map2ReplacementAnchors[i - 1])
463
+ .find(".mjx-mrow")
464
+ .eq(0)
465
+ .invoke("text")
466
+ .then((text) => {
467
+ expect(text.trim().replace(/−/g, "-")).equal(
468
+ clamp01(indToVal(i)).toString(),
469
+ );
470
+ });
471
+
472
+ cy.get(map3ReplacementAnchors[i - 1])
473
+ .find(".mjx-mrow")
474
+ .eq(0)
475
+ .invoke("text")
476
+ .then((text) => {
477
+ expect(text.trim().replace(/−/g, "-")).equal(
478
+ clampn35(indToVal(i)).toString(),
479
+ );
480
+ });
481
+ }
482
+
483
+ cy.log("check mapped state values");
484
+ cy.window().then(async (win) => {
485
+ for (let i = 1; i <= 5; i++) {
486
+ expect(
487
+ stateVariables[map1Replacements[i - 1].componentName].stateValues
488
+ .value,
489
+ ).closeTo(indToVal(i), 1e-10);
490
+ expect(
491
+ stateVariables[map2Replacements[i - 1].componentName].stateValues
492
+ .value,
493
+ ).closeTo(clamp01(indToVal(i)), 1e-10);
494
+ expect(
495
+ stateVariables[map3Replacements[i - 1].componentName].stateValues
496
+ .value,
497
+ ).closeTo(clampn35(indToVal(i)), 1e-10);
498
+ }
499
+ });
500
+
501
+ cy.log("check functions created from fDefinition");
502
+ cy.window().then(async (win) => {
503
+ let f01 = createFunctionFromDefinition(
504
+ stateVariables["/clamp01"].stateValues.fDefinitions[0],
505
+ );
506
+ let fn35 = createFunctionFromDefinition(
507
+ stateVariables["/clampn35"].stateValues.fDefinitions[0],
508
+ );
509
+
510
+ for (let i = 1; i <= 5; i++) {
511
+ let x = i - 3;
512
+ expect(f01(x)).closeTo(clamp01(indToVal(i)), 1e-10);
513
+ expect(fn35(x)).closeTo(clampn35(indToVal(i)), 1e-10);
514
+ }
515
+ });
516
+ });
517
+ });
518
+
519
+ it("wrap function", () => {
520
+ cy.window().then(async (win) => {
521
+ win.postMessage(
522
+ {
523
+ doenetML: `
524
+ <text>a</text>
525
+ <function name="original" displayDecimals="3" ignoreDisplayDigits>x^3</function>
526
+ <wrapfunctionperiodic name="wrap01"><copy target="original" /></wrapfunctionperiodic>
527
+ <wrapfunctionperiodic name="wrapn23" lowervalue="-2" uppervalue="3"><copy target="original" /></wrapfunctionperiodic>
528
+
529
+ <p><aslist>
530
+ <map>
531
+ <template newNamespace>$$(../original)($x)</template>
532
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
533
+ </map>
534
+ </aslist></p>
535
+ <p><aslist>
536
+ <map>
537
+ <template newNamespace><evaluate function="$(../wrap01)" input="$x" /></template>
538
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
539
+ </map>
540
+ </aslist></p>
541
+ <p><aslist>
542
+ <map>
543
+ <template newNamespace>$$(../wrapn23)($x)</template>
544
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
545
+ </map>
546
+ </aslist></p>
547
+ <p><aslist>
548
+ <copy target="_map2" name="m4" />
549
+ </aslist></p>
550
+ <p><aslist>
551
+ <copy target="_map3" name="m5" />
552
+ </aslist></p>
553
+ `,
554
+ },
555
+ "*",
556
+ );
557
+ });
558
+
559
+ cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded
560
+
561
+ cy.window().then(async (win) => {
562
+ let stateVariables = await win.returnAllStateVariables1();
563
+ let map1Replacements = stateVariables["/_map1"].replacements.reduce(
564
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
565
+ [],
566
+ );
567
+ let map1ReplacementAnchors = map1Replacements.map((x) =>
568
+ cesc2("#" + x.componentName),
569
+ );
570
+ let map2Replacements = stateVariables["/_map2"].replacements.reduce(
571
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
572
+ [],
573
+ );
574
+ let map2ReplacementAnchors = map2Replacements.map((x) =>
575
+ cesc2("#" + x.componentName),
576
+ );
577
+ let map3Replacements = stateVariables["/_map3"].replacements.reduce(
578
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
579
+ [],
580
+ );
581
+ let map3ReplacementAnchors = map3Replacements.map((x) =>
582
+ cesc2("#" + x.componentName),
583
+ );
584
+ let map4Replacements = stateVariables["/m4"].replacements.reduce(
585
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
586
+ [],
587
+ );
588
+ let map4ReplacementAnchors = map4Replacements.map((x) =>
589
+ cesc2("#" + x.componentName),
590
+ );
591
+ let map5Replacements = stateVariables["/m5"].replacements.reduce(
592
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
593
+ [],
594
+ );
595
+ let map5ReplacementAnchors = map5Replacements.map((x) =>
596
+ cesc2("#" + x.componentName),
597
+ );
598
+
599
+ let wrap01 = (x) => me.math.round(me.math.mod(x, 1), 3);
600
+ let wrapn23 = (x) => me.math.round(-2 + me.math.mod(x + 2, 5), 3);
601
+ let indToVal = (ind) => me.math.round((0.2 * (ind - 11)) ** 3, 3);
602
+
603
+ cy.log("Check values in DOM");
604
+
605
+ for (let i = 1; i <= 21; i++) {
606
+ cy.get(map1ReplacementAnchors[i - 1])
607
+ .find(".mjx-mrow")
608
+ .eq(0)
609
+ .invoke("text")
610
+ .then((text) => {
611
+ expect(text.trim().replace(/−/g, "-")).equal(
612
+ indToVal(i).toString(),
613
+ );
614
+ });
615
+
616
+ cy.get(map2ReplacementAnchors[i - 1])
617
+ .find(".mjx-mrow")
618
+ .eq(0)
619
+ .invoke("text")
620
+ .then((text) => {
621
+ expect(text.trim().replace(/−/g, "-")).equal(
622
+ wrap01(indToVal(i)).toString(),
623
+ );
624
+ });
625
+
626
+ cy.get(map3ReplacementAnchors[i - 1])
627
+ .find(".mjx-mrow")
628
+ .eq(0)
629
+ .invoke("text")
630
+ .then((text) => {
631
+ expect(text.trim().replace(/−/g, "-")).equal(
632
+ wrapn23(indToVal(i)).toString(),
633
+ );
634
+ });
635
+
636
+ cy.get(map4ReplacementAnchors[i - 1])
637
+ .find(".mjx-mrow")
638
+ .eq(0)
639
+ .invoke("text")
640
+ .then((text) => {
641
+ expect(text.trim().replace(/−/g, "-")).equal(
642
+ wrap01(indToVal(i)).toString(),
643
+ );
644
+ });
645
+
646
+ cy.get(map5ReplacementAnchors[i - 1])
647
+ .find(".mjx-mrow")
648
+ .eq(0)
649
+ .invoke("text")
650
+ .then((text) => {
651
+ expect(text.trim().replace(/−/g, "-")).equal(
652
+ wrapn23(indToVal(i)).toString(),
653
+ );
654
+ });
655
+ }
656
+
657
+ cy.log("check mapped state values");
658
+ cy.window().then(async (win) => {
659
+ for (let i = 1; i <= 21; i++) {
660
+ expect(
661
+ stateVariables[map1Replacements[i - 1].componentName].stateValues
662
+ .value,
663
+ ).closeTo(indToVal(i), 1e-10);
664
+ expect(
665
+ stateVariables[map2Replacements[i - 1].componentName].stateValues
666
+ .value,
667
+ ).closeTo(wrap01(indToVal(i)), 1e-10);
668
+ expect(
669
+ stateVariables[map3Replacements[i - 1].componentName].stateValues
670
+ .value,
671
+ ).closeTo(wrapn23(indToVal(i)), 1e-10);
672
+ expect(
673
+ stateVariables[map4Replacements[i - 1].componentName].stateValues
674
+ .value,
675
+ ).closeTo(wrap01(indToVal(i)), 1e-10);
676
+ expect(
677
+ stateVariables[map5Replacements[i - 1].componentName].stateValues
678
+ .value,
679
+ ).closeTo(wrapn23(indToVal(i)), 1e-10);
680
+ }
681
+ });
682
+
683
+ cy.log("check functions created from fDefinition");
684
+ cy.window().then(async (win) => {
685
+ let f01 = createFunctionFromDefinition(
686
+ stateVariables["/wrap01"].stateValues.fDefinitions[0],
687
+ );
688
+ let fn23 = createFunctionFromDefinition(
689
+ stateVariables["/wrapn23"].stateValues.fDefinitions[0],
690
+ );
691
+
692
+ for (let i = 1; i <= 21; i++) {
693
+ let x = 0.2 * (i - 11);
694
+ expect(f01(x)).closeTo(wrap01(indToVal(i)), 1e-10);
695
+ expect(fn23(x)).closeTo(wrapn23(indToVal(i)), 1e-10);
696
+ }
697
+ });
698
+ });
699
+ });
700
+
701
+ it("wrap function, numeric", () => {
702
+ cy.window().then(async (win) => {
703
+ win.postMessage(
704
+ {
705
+ doenetML: `
706
+ <text>a</text>
707
+ <function name="original" symbolic="false" displayDecimals="3" ignoreDisplayDigits>x^3</function>
708
+ <wrapfunctionperiodic name="wrap01"><copy target="original" /></wrapfunctionperiodic>
709
+ <wrapfunctionperiodic name="wrapn23" lowervalue="-2" uppervalue="3"><copy target="original" /></wrapfunctionperiodic>
710
+
711
+ <p><aslist>
712
+ <map>
713
+ <template newNamespace>$$(../original)($x)</template>
714
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
715
+ </map>
716
+ </aslist></p>
717
+ <p><aslist>
718
+ <map>
719
+ <template newNamespace><evaluate function="$(../wrap01)" input="$x" /></template>
720
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
721
+ </map>
722
+ </aslist></p>
723
+ <p><aslist>
724
+ <map>
725
+ <template newNamespace>$$(../wrapn23)($x)</template>
726
+ <sources alias="x"><sequence step="0.2" from="-2" to="2" /></sources>
727
+ </map>
728
+ </aslist></p>
729
+ <p><aslist>
730
+ <copy target="_map2" name="m4" />
731
+ </aslist></p>
732
+ <p><aslist>
733
+ <copy target="_map3" name="m5" />
734
+ </aslist></p>
735
+ `,
736
+ },
737
+ "*",
738
+ );
739
+ });
740
+
741
+ cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded
742
+
743
+ cy.window().then(async (win) => {
744
+ let stateVariables = await win.returnAllStateVariables1();
745
+ let map1Replacements = stateVariables["/_map1"].replacements.reduce(
746
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
747
+ [],
748
+ );
749
+ let map1ReplacementAnchors = map1Replacements.map((x) =>
750
+ cesc2("#" + x.componentName),
751
+ );
752
+ let map2Replacements = stateVariables["/_map2"].replacements.reduce(
753
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
754
+ [],
755
+ );
756
+ let map2ReplacementAnchors = map2Replacements.map((x) =>
757
+ cesc2("#" + x.componentName),
758
+ );
759
+ let map3Replacements = stateVariables["/_map3"].replacements.reduce(
760
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
761
+ [],
762
+ );
763
+ let map3ReplacementAnchors = map3Replacements.map((x) =>
764
+ cesc2("#" + x.componentName),
765
+ );
766
+ let map4Replacements = stateVariables["/m4"].replacements.reduce(
767
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
768
+ [],
769
+ );
770
+ let map4ReplacementAnchors = map4Replacements.map((x) =>
771
+ cesc2("#" + x.componentName),
772
+ );
773
+ let map5Replacements = stateVariables["/m5"].replacements.reduce(
774
+ (a, c) => [...a, ...stateVariables[c.componentName].replacements],
775
+ [],
776
+ );
777
+ let map5ReplacementAnchors = map5Replacements.map((x) =>
778
+ cesc2("#" + x.componentName),
779
+ );
780
+
781
+ let wrap01 = (x) => me.math.round(me.math.mod(x, 1), 3);
782
+ let wrapn23 = (x) => me.math.round(-2 + me.math.mod(x + 2, 5), 3);
783
+ let indToVal = (ind) => me.math.round((0.2 * (ind - 11)) ** 3, 3);
784
+
785
+ cy.log("Check values in DOM");
786
+
787
+ for (let i = 1; i <= 21; i++) {
788
+ cy.get(map1ReplacementAnchors[i - 1])
789
+ .find(".mjx-mrow")
790
+ .eq(0)
791
+ .invoke("text")
792
+ .then((text) => {
793
+ expect(text.trim().replace(/−/g, "-")).equal(
794
+ indToVal(i).toString(),
795
+ );
796
+ });
797
+
798
+ cy.get(map2ReplacementAnchors[i - 1])
799
+ .find(".mjx-mrow")
800
+ .eq(0)
801
+ .invoke("text")
802
+ .then((text) => {
803
+ expect(text.trim().replace(/−/g, "-")).equal(
804
+ wrap01(indToVal(i)).toString(),
805
+ );
806
+ });
807
+
808
+ cy.get(map3ReplacementAnchors[i - 1])
809
+ .find(".mjx-mrow")
810
+ .eq(0)
811
+ .invoke("text")
812
+ .then((text) => {
813
+ expect(text.trim().replace(/−/g, "-")).equal(
814
+ wrapn23(indToVal(i)).toString(),
815
+ );
816
+ });
817
+
818
+ cy.get(map4ReplacementAnchors[i - 1])
819
+ .find(".mjx-mrow")
820
+ .eq(0)
821
+ .invoke("text")
822
+ .then((text) => {
823
+ expect(text.trim().replace(/−/g, "-")).equal(
824
+ wrap01(indToVal(i)).toString(),
825
+ );
826
+ });
827
+
828
+ cy.get(map5ReplacementAnchors[i - 1])
829
+ .find(".mjx-mrow")
830
+ .eq(0)
831
+ .invoke("text")
832
+ .then((text) => {
833
+ expect(text.trim().replace(/−/g, "-")).equal(
834
+ wrapn23(indToVal(i)).toString(),
835
+ );
836
+ });
837
+ }
838
+
839
+ cy.log("check mapped state values");
840
+ cy.window().then(async (win) => {
841
+ for (let i = 1; i <= 21; i++) {
842
+ expect(
843
+ stateVariables[map1Replacements[i - 1].componentName].stateValues
844
+ .value,
845
+ ).closeTo(indToVal(i), 1e-10);
846
+ expect(
847
+ stateVariables[map2Replacements[i - 1].componentName].stateValues
848
+ .value,
849
+ ).closeTo(wrap01(indToVal(i)), 1e-10);
850
+ expect(
851
+ stateVariables[map3Replacements[i - 1].componentName].stateValues
852
+ .value,
853
+ ).closeTo(wrapn23(indToVal(i)), 1e-10);
854
+ expect(
855
+ stateVariables[map4Replacements[i - 1].componentName].stateValues
856
+ .value,
857
+ ).closeTo(wrap01(indToVal(i)), 1e-10);
858
+ expect(
859
+ stateVariables[map5Replacements[i - 1].componentName].stateValues
860
+ .value,
861
+ ).closeTo(wrapn23(indToVal(i)), 1e-10);
862
+ }
863
+ });
864
+
865
+ cy.log("check functions created from fDefinition");
866
+ cy.window().then(async (win) => {
867
+ let f01 = createFunctionFromDefinition(
868
+ stateVariables["/wrap01"].stateValues.fDefinitions[0],
869
+ );
870
+ let fn23 = createFunctionFromDefinition(
871
+ stateVariables["/wrapn23"].stateValues.fDefinitions[0],
872
+ );
873
+
874
+ for (let i = 1; i <= 21; i++) {
875
+ let x = 0.2 * (i - 11);
876
+ expect(f01(x)).closeTo(wrap01(indToVal(i)), 1e-10);
877
+ expect(fn23(x)).closeTo(wrapn23(indToVal(i)), 1e-10);
878
+ }
879
+ });
880
+ });
881
+ });
882
+
883
+ it("derivative", () => {
884
+ cy.window().then(async (win) => {
885
+ win.postMessage(
886
+ {
887
+ doenetML: `
888
+ <text>a</text>
889
+ <p><m>a =</m> <mathinput name="a" prefill="1" /></p>
890
+ <p><m>b =</m> <mathinput name="b" prefill="1" /></p>
891
+ <p><m>c =</m> <mathinput name="c" prefill="1" /></p>
892
+ <p><m>x =</m> <mathinput name="x" prefill="x" /></p>
893
+
894
+ <math hide name="formula" simplify>
895
+ $a sin($b$x + $c)
896
+ </math>
897
+
898
+ <p><m>f($x) =
899
+ <function name="f" variable="$x">$formula</function>
900
+ </m></p>
901
+
902
+ <p><m>f'($x) =
903
+ <derivative name="g">$f</derivative>
904
+ </m></p>
905
+
906
+ <graph>
907
+ $f
908
+ $g
909
+ <point x="3" y="4">
910
+ <constraints>
911
+ <constrainTo>$f</constrainTo>
912
+ </constraints>
913
+ </point>
914
+ <point x="3" y="4">
915
+ <constraints>
916
+ <constrainTo>$g</constrainTo>
917
+ </constraints>
918
+ </point>
919
+ </graph>
920
+
921
+ `,
922
+ },
923
+ "*",
924
+ );
925
+ });
926
+
927
+ cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded
928
+
929
+ cy.get(cesc2("#/_m5"))
930
+ .find(".mjx-mrow")
931
+ .eq(0)
932
+ .invoke("text")
933
+ .then((text) => {
934
+ expect(text.trim()).equal("f(x)=sin(x+1)");
935
+ });
936
+ cy.get(cesc2("#/_m6"))
937
+ .find(".mjx-mrow")
938
+ .eq(0)
939
+ .invoke("text")
940
+ .then((text) => {
941
+ expect(text.trim()).equal("f′(x)=cos(x+1)");
942
+ });
943
+
944
+ cy.window().then(async (win) => {
945
+ let stateVariables = await win.returnAllStateVariables1();
946
+ let x1 = 3,
947
+ y1 = Math.sin(4);
948
+ let x2 = 3,
949
+ y2 = Math.cos(4);
950
+
951
+ expect(
952
+ me.fromAst(stateVariables["/f"].stateValues.formula).toString(),
953
+ ).eq("sin(x + 1)");
954
+ expect(
955
+ me.fromAst(stateVariables["/g"].stateValues.formula).toString(),
956
+ ).eq("cos(x + 1)");
957
+ expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo(x1, 1e-12);
958
+ expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo(y1, 1e-12);
959
+ expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo(x2, 1e-12);
960
+ expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo(y2, 1e-12);
961
+
962
+ let f = createFunctionFromDefinition(
963
+ stateVariables["/f"].stateValues.fDefinitions[0],
964
+ );
965
+ let g = createFunctionFromDefinition(
966
+ stateVariables["/g"].stateValues.fDefinitions[0],
967
+ );
968
+
969
+ for (let i = 1; i <= 21; i++) {
970
+ let x = 0.2 * (i - 11);
971
+ expect(f(x)).closeTo(Math.sin(x + 1), 1e-10);
972
+ expect(g(x)).closeTo(Math.cos(x + 1), 1e-10);
973
+ }
974
+ });
975
+
976
+ cy.window().then(async (win) => {
977
+ let x1 = -3,
978
+ y1 = Math.sin(-2);
979
+ let x2 = 5,
980
+ y2 = Math.cos(6);
981
+
982
+ await win.callAction1({
983
+ actionName: "movePoint",
984
+ componentName: "/_point1",
985
+ args: { x: x1, y: y1 },
986
+ });
987
+ await win.callAction1({
988
+ actionName: "movePoint",
989
+ componentName: "/_point2",
990
+ args: { x: x2, y: y2 },
991
+ });
992
+
993
+ let stateVariables = await win.returnAllStateVariables1();
994
+
995
+ expect(
996
+ me.fromAst(stateVariables["/f"].stateValues.formula).toString(),
997
+ ).eq("sin(x + 1)");
998
+ expect(
999
+ me.fromAst(stateVariables["/g"].stateValues.formula).toString(),
1000
+ ).eq("cos(x + 1)");
1001
+ expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo(x1, 1e-12);
1002
+ expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo(y1, 1e-12);
1003
+ expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo(x2, 1e-12);
1004
+ expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo(y2, 1e-12);
1005
+ });
1006
+
1007
+ cy.get(cesc2("#/a") + " textarea").type(`{end}{backspace}2`, {
1008
+ force: true,
1009
+ });
1010
+ cy.get(cesc2("#/b") + " textarea").type(`{end}{backspace}pi`, {
1011
+ force: true,
1012
+ });
1013
+ cy.get(cesc2("#/c") + " textarea").type(`{end}{backspace}e`, {
1014
+ force: true,
1015
+ });
1016
+ cy.get(cesc2("#/x") + " textarea")
1017
+ .type(`{end}{backspace}q`, { force: true })
1018
+ .blur();
1019
+
1020
+ cy.get(cesc2("#/_m5") + " .mjx-mrow").should(
1021
+ "contain.text",
1022
+ "f(q)=2sin(e+πq)",
1023
+ );
1024
+ cy.get(cesc2("#/_m5"))
1025
+ .find(".mjx-mrow")
1026
+ .eq(0)
1027
+ .invoke("text")
1028
+ .then((text) => {
1029
+ expect(text.trim()).equal("f(q)=2sin(e+πq)");
1030
+ });
1031
+ cy.get(cesc2("#/_m6"))
1032
+ .find(".mjx-mrow")
1033
+ .eq(0)
1034
+ .invoke("text")
1035
+ .then((text) => {
1036
+ expect(text.trim()).equal("f′(q)=2πcos(e+πq)");
1037
+ });
1038
+
1039
+ cy.window().then(async (win) => {
1040
+ let stateVariables = await win.returnAllStateVariables1();
1041
+ let x1 = -3,
1042
+ y1 = 2 * Math.sin(Math.PI * -3 + Math.E);
1043
+ let x2 = 5,
1044
+ y2 = 2 * Math.PI * Math.cos(Math.PI * 5 + Math.E);
1045
+
1046
+ expect(
1047
+ me.fromAst(stateVariables["/f"].stateValues.formula).toString(),
1048
+ ).eq("2 sin(e + π q)");
1049
+ expect(
1050
+ me.fromAst(stateVariables["/g"].stateValues.formula).toString(),
1051
+ ).eq("2 π cos(e + π q)");
1052
+ expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo(x1, 1e-12);
1053
+ expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo(y1, 1e-12);
1054
+ expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo(x2, 1e-12);
1055
+ expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo(y2, 1e-12);
1056
+
1057
+ let f = createFunctionFromDefinition(
1058
+ stateVariables["/f"].stateValues.fDefinitions[0],
1059
+ );
1060
+ let g = createFunctionFromDefinition(
1061
+ stateVariables["/g"].stateValues.fDefinitions[0],
1062
+ );
1063
+
1064
+ for (let i = 1; i <= 21; i++) {
1065
+ let x = 0.2 * (i - 11);
1066
+ expect(f(x)).closeTo(2 * Math.sin(Math.PI * x + Math.E), 1e-10);
1067
+ expect(g(x)).closeTo(
1068
+ 2 * Math.PI * Math.cos(Math.PI * x + Math.E),
1069
+ 1e-10,
1070
+ );
1071
+ }
1072
+ });
1073
+
1074
+ cy.window().then(async (win) => {
1075
+ let x1 = 9,
1076
+ y1 = 2 * Math.sin(Math.PI * 9 + Math.E);
1077
+ let x2 = -7,
1078
+ y2 = 2 * Math.PI * Math.cos(Math.PI * -7 + Math.E);
1079
+
1080
+ await win.callAction1({
1081
+ actionName: "movePoint",
1082
+ componentName: "/_point1",
1083
+ args: { x: x1, y: y1 },
1084
+ });
1085
+ await win.callAction1({
1086
+ actionName: "movePoint",
1087
+ componentName: "/_point2",
1088
+ args: { x: x2, y: y2 },
1089
+ });
1090
+
1091
+ let stateVariables = await win.returnAllStateVariables1();
1092
+
1093
+ expect(
1094
+ me.fromAst(stateVariables["/f"].stateValues.formula).toString(),
1095
+ ).eq("2 sin(e + π q)");
1096
+ expect(
1097
+ me.fromAst(stateVariables["/g"].stateValues.formula).toString(),
1098
+ ).eq("2 π cos(e + π q)");
1099
+ expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo(x1, 1e-12);
1100
+ expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo(y1, 1e-12);
1101
+ expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo(x2, 1e-12);
1102
+ expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo(y2, 1e-12);
1103
+ });
1104
+ });
1105
+
1106
+ it("derivative 2", () => {
1107
+ cy.window().then(async (win) => {
1108
+ win.postMessage(
1109
+ {
1110
+ doenetML: `
1111
+ <text>a</text>
1112
+ <function name="f1">sin(x)</function>
1113
+ <function name="f2" variables="y">e^(2y)</function>
1114
+ <function name="f3">xyz</function>
1115
+ <function name="f4" variable="z">xyz</function>
1116
+ <derivative name="d1"><function>x^2</function></derivative>
1117
+ <derivative name="d2"><math name="x2">x^2</math></derivative>
1118
+ <derivative name="d2b">$x2</derivative>
1119
+ <derivative name="d2c"><copy target="x2" /></derivative>
1120
+ <derivative name="d3"><function>x^2sin(z)</function></derivative>
1121
+ <derivative name="d4" variables="z">x^2sin(z)</derivative>
1122
+ <math name='var'>z</math><number name="a">2</number>
1123
+ <derivative name="d4b" variable="$var">x^$a sin($var)</derivative>
1124
+ <derivative name="d5"><copy target="f1" /></derivative>
1125
+ <derivative name="d5b">$f1</derivative>
1126
+ <derivative name="d6"><copy target="f2" /></derivative>
1127
+ <derivative name="d6b">$f2</derivative>
1128
+ <derivative name="d7"><copy target="f3" /></derivative>
1129
+ <derivative name="d7b">$f3</derivative>
1130
+ <derivative name="d8"><copy target="f4" /></derivative>
1131
+ <derivative name="d8b">$f4</derivative>
1132
+ <derivative variables="q" name="d9"><copy target="f1" /></derivative>
1133
+ <derivative variable="q" name="d10"><copy target="f2" /></derivative>
1134
+ <derivative variables="q" name="d11"><copy target="f3" /></derivative>
1135
+ <derivative variable="q" name="d12"><copy target="f4" /></derivative>
1136
+ <derivative variables="y" name="d13"><copy target="f3" /></derivative>
1137
+ <derivative variable="y" name="d14"><copy target="f4" /></derivative>
1138
+ `,
1139
+ },
1140
+ "*",
1141
+ );
1142
+ });
1143
+
1144
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
1145
+
1146
+ cy.window().then(async (win) => {
1147
+ let stateVariables = await win.returnAllStateVariables1();
1148
+ expect(
1149
+ me
1150
+ .fromAst(stateVariables["/d1"].stateValues.formula)
1151
+ .equals(me.fromText("2x")),
1152
+ ).eq(true);
1153
+ expect(
1154
+ me
1155
+ .fromAst(stateVariables["/d2"].stateValues.formula)
1156
+ .equals(me.fromText("2x")),
1157
+ ).eq(true);
1158
+ expect(
1159
+ me
1160
+ .fromAst(stateVariables["/d2b"].stateValues.formula)
1161
+ .equals(me.fromText("2x")),
1162
+ ).eq(true);
1163
+ expect(
1164
+ me
1165
+ .fromAst(stateVariables["/d2c"].stateValues.formula)
1166
+ .equals(me.fromText("2x")),
1167
+ ).eq(true);
1168
+ expect(
1169
+ me
1170
+ .fromAst(stateVariables["/d3"].stateValues.formula)
1171
+ .equals(me.fromText("2x sin(z)")),
1172
+ ).eq(true);
1173
+ expect(
1174
+ me
1175
+ .fromAst(stateVariables["/d4"].stateValues.formula)
1176
+ .equals(me.fromText("x^2cos(z)")),
1177
+ ).eq(true);
1178
+ expect(
1179
+ me
1180
+ .fromAst(stateVariables["/d4b"].stateValues.formula)
1181
+ .equals(me.fromText("x^2cos(z)")),
1182
+ ).eq(true);
1183
+ expect(
1184
+ me
1185
+ .fromAst(stateVariables["/d5"].stateValues.formula)
1186
+ .equals(me.fromText("cos(x)")),
1187
+ ).eq(true);
1188
+ expect(
1189
+ me
1190
+ .fromAst(stateVariables["/d5b"].stateValues.formula)
1191
+ .equals(me.fromText("cos(x)")),
1192
+ ).eq(true);
1193
+ expect(
1194
+ me
1195
+ .fromAst(stateVariables["/d6"].stateValues.formula)
1196
+ .equals(me.fromText("2e^(2y)")),
1197
+ ).eq(true);
1198
+ expect(
1199
+ me
1200
+ .fromAst(stateVariables["/d6b"].stateValues.formula)
1201
+ .equals(me.fromText("2e^(2y)")),
1202
+ ).eq(true);
1203
+ expect(
1204
+ me
1205
+ .fromAst(stateVariables["/d7"].stateValues.formula)
1206
+ .equals(me.fromText("yz")),
1207
+ ).eq(true);
1208
+ expect(
1209
+ me
1210
+ .fromAst(stateVariables["/d7b"].stateValues.formula)
1211
+ .equals(me.fromText("yz")),
1212
+ ).eq(true);
1213
+ expect(
1214
+ me
1215
+ .fromAst(stateVariables["/d8"].stateValues.formula)
1216
+ .equals(me.fromText("xy")),
1217
+ ).eq(true);
1218
+ expect(
1219
+ me
1220
+ .fromAst(stateVariables["/d8b"].stateValues.formula)
1221
+ .equals(me.fromText("xy")),
1222
+ ).eq(true);
1223
+ expect(
1224
+ me
1225
+ .fromAst(stateVariables["/d9"].stateValues.formula)
1226
+ .equals(me.fromText("0")),
1227
+ ).eq(true);
1228
+ expect(
1229
+ me
1230
+ .fromAst(stateVariables["/d10"].stateValues.formula)
1231
+ .equals(me.fromText("0")),
1232
+ ).eq(true);
1233
+ expect(
1234
+ me
1235
+ .fromAst(stateVariables["/d11"].stateValues.formula)
1236
+ .equals(me.fromText("0")),
1237
+ ).eq(true);
1238
+ expect(
1239
+ me
1240
+ .fromAst(stateVariables["/d12"].stateValues.formula)
1241
+ .equals(me.fromText("0")),
1242
+ ).eq(true);
1243
+ expect(
1244
+ me
1245
+ .fromAst(stateVariables["/d13"].stateValues.formula)
1246
+ .equals(me.fromText("xz")),
1247
+ ).eq(true);
1248
+ expect(
1249
+ me
1250
+ .fromAst(stateVariables["/d14"].stateValues.formula)
1251
+ .equals(me.fromText("xz")),
1252
+ ).eq(true);
1253
+
1254
+ let d1 = createFunctionFromDefinition(
1255
+ stateVariables["/d1"].stateValues.fDefinitions[0],
1256
+ );
1257
+ let d2 = createFunctionFromDefinition(
1258
+ stateVariables["/d2"].stateValues.fDefinitions[0],
1259
+ );
1260
+ let d2b = createFunctionFromDefinition(
1261
+ stateVariables["/d2b"].stateValues.fDefinitions[0],
1262
+ );
1263
+ let d2c = createFunctionFromDefinition(
1264
+ stateVariables["/d2c"].stateValues.fDefinitions[0],
1265
+ );
1266
+ let d5 = createFunctionFromDefinition(
1267
+ stateVariables["/d5"].stateValues.fDefinitions[0],
1268
+ );
1269
+ let d5b = createFunctionFromDefinition(
1270
+ stateVariables["/d5b"].stateValues.fDefinitions[0],
1271
+ );
1272
+ let d6 = createFunctionFromDefinition(
1273
+ stateVariables["/d6"].stateValues.fDefinitions[0],
1274
+ );
1275
+ let d6b = createFunctionFromDefinition(
1276
+ stateVariables["/d6b"].stateValues.fDefinitions[0],
1277
+ );
1278
+ let d9 = createFunctionFromDefinition(
1279
+ stateVariables["/d9"].stateValues.fDefinitions[0],
1280
+ );
1281
+ let d10 = createFunctionFromDefinition(
1282
+ stateVariables["/d10"].stateValues.fDefinitions[0],
1283
+ );
1284
+ let d11 = createFunctionFromDefinition(
1285
+ stateVariables["/d11"].stateValues.fDefinitions[0],
1286
+ );
1287
+ let d12 = createFunctionFromDefinition(
1288
+ stateVariables["/d12"].stateValues.fDefinitions[0],
1289
+ );
1290
+
1291
+ for (let i = 1; i <= 21; i++) {
1292
+ let x = 0.2 * (i - 11);
1293
+ expect(d1(x)).closeTo(2 * x, 1e-10);
1294
+ expect(d2(x)).closeTo(2 * x, 1e-10);
1295
+ expect(d2b(x)).closeTo(2 * x, 1e-10);
1296
+ expect(d2c(x)).closeTo(2 * x, 1e-10);
1297
+ expect(d5(x)).closeTo(Math.cos(x), 1e-10);
1298
+ expect(d5b(x)).closeTo(Math.cos(x), 1e-10);
1299
+ expect(d6(x)).closeTo(2 * Math.exp(2 * x), 1e-10);
1300
+ expect(d6b(x)).closeTo(2 * Math.exp(2 * x), 1e-10);
1301
+ expect(d9(x)).closeTo(0, 1e-10);
1302
+ expect(d10(x)).closeTo(0, 1e-10);
1303
+ expect(d11(x)).closeTo(0, 1e-10);
1304
+ expect(d12(x)).closeTo(0, 1e-10);
1305
+ }
1306
+ });
1307
+ });
1308
+
1309
+ it("derivative 2, labeled", () => {
1310
+ cy.window().then(async (win) => {
1311
+ win.postMessage(
1312
+ {
1313
+ doenetML: `
1314
+ <text>a</text>
1315
+ <function name="f1">sin(x)</function>
1316
+ <function name="f2" variable="y">e^(2y)</function>
1317
+ <function name="f3">xyz</function>
1318
+ <function name="f4" variables="z">xyz</function>
1319
+ <derivative name="d1"><function>x^2</function><label>d1</label></derivative>
1320
+ <derivative name="d2"><label>d2</label><math name="x2">x^2</math></derivative>
1321
+ <derivative name="d2b">$x2<label>d2b</label></derivative>
1322
+ <derivative name="d2c"><label>d2c</label><copy target="x2" /></derivative>
1323
+ <derivative name="d3"><function>x^2sin(z)</function><label>d3</label></derivative>
1324
+ <derivative name="d4" variable="z"><label>d4</label>x^2sin(z)</derivative>
1325
+ <math name='var'>z</math><number name="a">2</number>
1326
+ <derivative name="d4b" variables="$var">x^$a sin($var)<label>d4b</label></derivative>
1327
+ <derivative name="d5"><label>d5</label><copy target="f1" /></derivative>
1328
+ <derivative name="d5b">$f1<label>d5b</label></derivative>
1329
+ <derivative name="d6"><copy target="f2" /><label>d6</label></derivative>
1330
+ <derivative name="d6b"><label>d6b</label>$f2</derivative>
1331
+ <derivative name="d7"><copy target="f3" /><label>d7</label></derivative>
1332
+ <derivative name="d7b"><label>d7b</label>$f3</derivative>
1333
+ <derivative name="d8"><label>d8</label><copy target="f4" /></derivative>
1334
+ <derivative name="d8b">$f4<label>d8b</label></derivative>
1335
+ <derivative variable="q" name="d9"><label>d9</label><copy target="f1" /></derivative>
1336
+ <derivative variables="q" name="d10"><copy target="f2" /><label>d10</label></derivative>
1337
+ <derivative variable="q" name="d11"><label>d11</label><copy target="f3" /></derivative>
1338
+ <derivative variables="q" name="d12"><copy target="f4" /><label>d12</label></derivative>
1339
+ <derivative variable="y" name="d13"><label>d13</label><copy target="f3" /></derivative>
1340
+ <derivative variables="y" name="d14"><copy target="f4" /><label>d14</label></derivative>
1341
+ `,
1342
+ },
1343
+ "*",
1344
+ );
1345
+ });
1346
+
1347
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
1348
+
1349
+ cy.window().then(async (win) => {
1350
+ let stateVariables = await win.returnAllStateVariables1();
1351
+
1352
+ expect(stateVariables["/d1"].stateValues.label).eq("d1");
1353
+ expect(stateVariables["/d2"].stateValues.label).eq("d2");
1354
+ expect(stateVariables["/d2b"].stateValues.label).eq("d2b");
1355
+ expect(stateVariables["/d2c"].stateValues.label).eq("d2c");
1356
+ expect(stateVariables["/d3"].stateValues.label).eq("d3");
1357
+ expect(stateVariables["/d4"].stateValues.label).eq("d4");
1358
+ expect(stateVariables["/d4b"].stateValues.label).eq("d4b");
1359
+ expect(stateVariables["/d5"].stateValues.label).eq("d5");
1360
+ expect(stateVariables["/d5b"].stateValues.label).eq("d5b");
1361
+ expect(stateVariables["/d6"].stateValues.label).eq("d6");
1362
+ expect(stateVariables["/d6b"].stateValues.label).eq("d6b");
1363
+ expect(stateVariables["/d7"].stateValues.label).eq("d7");
1364
+ expect(stateVariables["/d7b"].stateValues.label).eq("d7b");
1365
+ expect(stateVariables["/d8"].stateValues.label).eq("d8");
1366
+ expect(stateVariables["/d8b"].stateValues.label).eq("d8b");
1367
+ expect(stateVariables["/d9"].stateValues.label).eq("d9");
1368
+ expect(stateVariables["/d10"].stateValues.label).eq("d10");
1369
+ expect(stateVariables["/d11"].stateValues.label).eq("d11");
1370
+ expect(stateVariables["/d12"].stateValues.label).eq("d12");
1371
+ expect(stateVariables["/d13"].stateValues.label).eq("d13");
1372
+ expect(stateVariables["/d14"].stateValues.label).eq("d14");
1373
+
1374
+ expect(
1375
+ me
1376
+ .fromAst(stateVariables["/d1"].stateValues.formula)
1377
+ .equals(me.fromText("2x")),
1378
+ ).eq(true);
1379
+ expect(
1380
+ me
1381
+ .fromAst(stateVariables["/d2"].stateValues.formula)
1382
+ .equals(me.fromText("2x")),
1383
+ ).eq(true);
1384
+ expect(
1385
+ me
1386
+ .fromAst(stateVariables["/d2b"].stateValues.formula)
1387
+ .equals(me.fromText("2x")),
1388
+ ).eq(true);
1389
+ expect(
1390
+ me
1391
+ .fromAst(stateVariables["/d2c"].stateValues.formula)
1392
+ .equals(me.fromText("2x")),
1393
+ ).eq(true);
1394
+ expect(
1395
+ me
1396
+ .fromAst(stateVariables["/d3"].stateValues.formula)
1397
+ .equals(me.fromText("2x sin(z)")),
1398
+ ).eq(true);
1399
+ expect(
1400
+ me
1401
+ .fromAst(stateVariables["/d4"].stateValues.formula)
1402
+ .equals(me.fromText("x^2cos(z)")),
1403
+ ).eq(true);
1404
+ expect(
1405
+ me
1406
+ .fromAst(stateVariables["/d4b"].stateValues.formula)
1407
+ .equals(me.fromText("x^2cos(z)")),
1408
+ ).eq(true);
1409
+ expect(
1410
+ me
1411
+ .fromAst(stateVariables["/d5"].stateValues.formula)
1412
+ .equals(me.fromText("cos(x)")),
1413
+ ).eq(true);
1414
+ expect(
1415
+ me
1416
+ .fromAst(stateVariables["/d5b"].stateValues.formula)
1417
+ .equals(me.fromText("cos(x)")),
1418
+ ).eq(true);
1419
+ expect(
1420
+ me
1421
+ .fromAst(stateVariables["/d6"].stateValues.formula)
1422
+ .equals(me.fromText("2e^(2y)")),
1423
+ ).eq(true);
1424
+ expect(
1425
+ me
1426
+ .fromAst(stateVariables["/d6b"].stateValues.formula)
1427
+ .equals(me.fromText("2e^(2y)")),
1428
+ ).eq(true);
1429
+ expect(
1430
+ me
1431
+ .fromAst(stateVariables["/d7"].stateValues.formula)
1432
+ .equals(me.fromText("yz")),
1433
+ ).eq(true);
1434
+ expect(
1435
+ me
1436
+ .fromAst(stateVariables["/d7b"].stateValues.formula)
1437
+ .equals(me.fromText("yz")),
1438
+ ).eq(true);
1439
+ expect(
1440
+ me
1441
+ .fromAst(stateVariables["/d8"].stateValues.formula)
1442
+ .equals(me.fromText("xy")),
1443
+ ).eq(true);
1444
+ expect(
1445
+ me
1446
+ .fromAst(stateVariables["/d8b"].stateValues.formula)
1447
+ .equals(me.fromText("xy")),
1448
+ ).eq(true);
1449
+ expect(
1450
+ me
1451
+ .fromAst(stateVariables["/d9"].stateValues.formula)
1452
+ .equals(me.fromText("0")),
1453
+ ).eq(true);
1454
+ expect(
1455
+ me
1456
+ .fromAst(stateVariables["/d10"].stateValues.formula)
1457
+ .equals(me.fromText("0")),
1458
+ ).eq(true);
1459
+ expect(
1460
+ me
1461
+ .fromAst(stateVariables["/d11"].stateValues.formula)
1462
+ .equals(me.fromText("0")),
1463
+ ).eq(true);
1464
+ expect(
1465
+ me
1466
+ .fromAst(stateVariables["/d12"].stateValues.formula)
1467
+ .equals(me.fromText("0")),
1468
+ ).eq(true);
1469
+ expect(
1470
+ me
1471
+ .fromAst(stateVariables["/d13"].stateValues.formula)
1472
+ .equals(me.fromText("xz")),
1473
+ ).eq(true);
1474
+ expect(
1475
+ me
1476
+ .fromAst(stateVariables["/d14"].stateValues.formula)
1477
+ .equals(me.fromText("xz")),
1478
+ ).eq(true);
1479
+
1480
+ let d1 = createFunctionFromDefinition(
1481
+ stateVariables["/d1"].stateValues.fDefinitions[0],
1482
+ );
1483
+ let d2 = createFunctionFromDefinition(
1484
+ stateVariables["/d2"].stateValues.fDefinitions[0],
1485
+ );
1486
+ let d2b = createFunctionFromDefinition(
1487
+ stateVariables["/d2b"].stateValues.fDefinitions[0],
1488
+ );
1489
+ let d2c = createFunctionFromDefinition(
1490
+ stateVariables["/d2c"].stateValues.fDefinitions[0],
1491
+ );
1492
+ let d5 = createFunctionFromDefinition(
1493
+ stateVariables["/d5"].stateValues.fDefinitions[0],
1494
+ );
1495
+ let d5b = createFunctionFromDefinition(
1496
+ stateVariables["/d5b"].stateValues.fDefinitions[0],
1497
+ );
1498
+ let d6 = createFunctionFromDefinition(
1499
+ stateVariables["/d6"].stateValues.fDefinitions[0],
1500
+ );
1501
+ let d6b = createFunctionFromDefinition(
1502
+ stateVariables["/d6b"].stateValues.fDefinitions[0],
1503
+ );
1504
+ let d9 = createFunctionFromDefinition(
1505
+ stateVariables["/d9"].stateValues.fDefinitions[0],
1506
+ );
1507
+ let d10 = createFunctionFromDefinition(
1508
+ stateVariables["/d10"].stateValues.fDefinitions[0],
1509
+ );
1510
+ let d11 = createFunctionFromDefinition(
1511
+ stateVariables["/d11"].stateValues.fDefinitions[0],
1512
+ );
1513
+ let d12 = createFunctionFromDefinition(
1514
+ stateVariables["/d12"].stateValues.fDefinitions[0],
1515
+ );
1516
+
1517
+ for (let i = 1; i <= 5; i++) {
1518
+ let x = i - 3;
1519
+ expect(d1(x)).closeTo(2 * x, 1e-10);
1520
+ expect(d2(x)).closeTo(2 * x, 1e-10);
1521
+ expect(d2b(x)).closeTo(2 * x, 1e-10);
1522
+ expect(d2c(x)).closeTo(2 * x, 1e-10);
1523
+ expect(d5(x)).closeTo(Math.cos(x), 1e-10);
1524
+ expect(d5b(x)).closeTo(Math.cos(x), 1e-10);
1525
+ expect(d6(x)).closeTo(2 * Math.exp(2 * x), 1e-10);
1526
+ expect(d6b(x)).closeTo(2 * Math.exp(2 * x), 1e-10);
1527
+ expect(d9(x)).closeTo(0, 1e-10);
1528
+ expect(d10(x)).closeTo(0, 1e-10);
1529
+ expect(d11(x)).closeTo(0, 1e-10);
1530
+ expect(d12(x)).closeTo(0, 1e-10);
1531
+ }
1532
+ });
1533
+ });
1534
+
1535
+ it("specifying derivative variables of a function", () => {
1536
+ cy.window().then(async (win) => {
1537
+ win.postMessage(
1538
+ {
1539
+ doenetML: `
1540
+ <text>a</text>
1541
+ <p><aslist>
1542
+ <function name="f1" numInputs="3">sin(x+y^2)z</function>
1543
+ <function name="f2" variables="z y x">sin(x+y^2)z</function>
1544
+ <function name="f3" variables="x y">sin(x+y^2)z</function>
1545
+ <function name="f4" variables="x_1 x_2 x_3">sin(x_1+x_2^2)x_3</function>
1546
+ </aslist></p>
1547
+
1548
+ <p><aslist>
1549
+ <derivative name="d11">$f1</derivative>
1550
+ <derivative name="d12" variable="z">$f1</derivative>
1551
+ <derivative name="d13" derivVariables="x">$f1</derivative>
1552
+ <derivative name="d14" derivVariable="z">$f1</derivative>
1553
+ <derivative name="d15" derivVariables="y z">$f1</derivative>
1554
+ <derivative name="d16" derivVariables="x x y">$f1</derivative>
1555
+ <derivative name="d17" derivVariable="u">$f1</derivative>
1556
+ <derivative name="d18" derivVariables="x x y" variables="z">$f1</derivative>
1557
+ </aslist></p>
1558
+
1559
+ <p><aslist>
1560
+ <derivative name="d21">$f2</derivative>
1561
+ <derivative name="d22" variables="x">$f2</derivative>
1562
+ <derivative name="d23" derivVariable="x">$f2</derivative>
1563
+ <derivative name="d24" derivVariables="z">$f2</derivative>
1564
+ <derivative name="d25" derivVariables="y z">$f2</derivative>
1565
+ <derivative name="d26" derivVariables="x x y">$f2</derivative>
1566
+ <derivative name="d27" derivVariables="u">$f2</derivative>
1567
+ <derivative name="d28" derivVariables="x x y" variables="z">$f2</derivative>
1568
+ </aslist></p>
1569
+
1570
+ <p><aslist>
1571
+ <derivative name="d31">$f3</derivative>
1572
+ <derivative name="d32" variables="z">$f3</derivative>
1573
+ <derivative name="d33" derivVariables="x">$f3</derivative>
1574
+ <derivative name="d34" derivVariable="z">$f3</derivative>
1575
+ <derivative name="d35" derivVariables="y z">$f3</derivative>
1576
+ <derivative name="d36" derivVariables="x x y">$f3</derivative>
1577
+ <derivative name="d37" derivVariable="u">$f3</derivative>
1578
+ <derivative name="d38" derivVariables="x x y" variables="z">$f3</derivative>
1579
+ </aslist></p>
1580
+
1581
+ <p><aslist>
1582
+ <derivative name="d41">$f4</derivative>
1583
+ <derivative name="d42" derivVariables="x_1 x_2 x_3">$f4</derivative>
1584
+ <derivative name="d43" derivVariable="x">$f4</derivative>
1585
+ <derivative name="d44" derivVariables="x_1 x_2 x_3" variables="x_3 x_2 x_1">$f4</derivative>
1586
+ </aslist></p>
1587
+
1588
+ `,
1589
+ },
1590
+ "*",
1591
+ );
1592
+ });
1593
+
1594
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
1595
+
1596
+ cy.window().then(async (win) => {
1597
+ let stateVariables = await win.returnAllStateVariables1();
1598
+
1599
+ expect(
1600
+ me
1601
+ .fromAst(stateVariables["/d11"].stateValues.formula)
1602
+ .equals(me.fromText("cos(x+y^2)z")),
1603
+ ).eq(true);
1604
+ expect(stateVariables["/d11"].stateValues.variables).eqls([
1605
+ "x",
1606
+ "y",
1607
+ "z",
1608
+ ]);
1609
+ expect(stateVariables["/d11"].stateValues.derivVariables).eqls(["x"]);
1610
+
1611
+ expect(
1612
+ me
1613
+ .fromAst(stateVariables["/d12"].stateValues.formula)
1614
+ .equals(me.fromText("sin(x+y^2)")),
1615
+ ).eq(true);
1616
+ expect(stateVariables["/d12"].stateValues.variables).eqls(["z"]);
1617
+ expect(stateVariables["/d12"].stateValues.derivVariables).eqls(["z"]);
1618
+
1619
+ expect(
1620
+ me
1621
+ .fromAst(stateVariables["/d13"].stateValues.formula)
1622
+ .equals(me.fromText("cos(x+y^2)z")),
1623
+ ).eq(true);
1624
+ expect(stateVariables["/d13"].stateValues.variables).eqls([
1625
+ "x",
1626
+ "y",
1627
+ "z",
1628
+ ]);
1629
+ expect(stateVariables["/d13"].stateValues.derivVariables).eqls(["x"]);
1630
+
1631
+ expect(
1632
+ me
1633
+ .fromAst(stateVariables["/d14"].stateValues.formula)
1634
+ .equals(me.fromText("sin(x+y^2)")),
1635
+ ).eq(true);
1636
+ expect(stateVariables["/d14"].stateValues.variables).eqls([
1637
+ "x",
1638
+ "y",
1639
+ "z",
1640
+ ]);
1641
+ expect(stateVariables["/d14"].stateValues.derivVariables).eqls(["z"]);
1642
+
1643
+ expect(
1644
+ me
1645
+ .fromAst(stateVariables["/d15"].stateValues.formula)
1646
+ .equals(me.fromText("2 y cos(x+y^2)")),
1647
+ ).eq(true);
1648
+ expect(stateVariables["/d15"].stateValues.variables).eqls([
1649
+ "x",
1650
+ "y",
1651
+ "z",
1652
+ ]);
1653
+ expect(stateVariables["/d15"].stateValues.derivVariables).eqls([
1654
+ "y",
1655
+ "z",
1656
+ ]);
1657
+
1658
+ expect(
1659
+ me
1660
+ .fromAst(stateVariables["/d16"].stateValues.formula)
1661
+ .equals(me.fromText("-2 y cos(x+y^2)z")),
1662
+ ).eq(true);
1663
+ expect(stateVariables["/d16"].stateValues.variables).eqls([
1664
+ "x",
1665
+ "y",
1666
+ "z",
1667
+ ]);
1668
+ expect(stateVariables["/d16"].stateValues.derivVariables).eqls([
1669
+ "x",
1670
+ "x",
1671
+ "y",
1672
+ ]);
1673
+
1674
+ expect(
1675
+ me
1676
+ .fromAst(stateVariables["/d17"].stateValues.formula)
1677
+ .equals(me.fromText("0")),
1678
+ ).eq(true);
1679
+ expect(stateVariables["/d17"].stateValues.variables).eqls([
1680
+ "x",
1681
+ "y",
1682
+ "z",
1683
+ ]);
1684
+ expect(stateVariables["/d17"].stateValues.derivVariables).eqls(["u"]);
1685
+
1686
+ expect(
1687
+ me
1688
+ .fromAst(stateVariables["/d18"].stateValues.formula)
1689
+ .equals(me.fromText("-2 y cos(x+y^2)z")),
1690
+ ).eq(true);
1691
+ expect(stateVariables["/d18"].stateValues.variables).eqls(["z"]);
1692
+ expect(stateVariables["/d18"].stateValues.derivVariables).eqls([
1693
+ "x",
1694
+ "x",
1695
+ "y",
1696
+ ]);
1697
+
1698
+ expect(
1699
+ me
1700
+ .fromAst(stateVariables["/d21"].stateValues.formula)
1701
+ .equals(me.fromText("sin(x+y^2)")),
1702
+ ).eq(true);
1703
+ expect(stateVariables["/d21"].stateValues.variables).eqls([
1704
+ "z",
1705
+ "y",
1706
+ "x",
1707
+ ]);
1708
+ expect(stateVariables["/d21"].stateValues.derivVariables).eqls(["z"]);
1709
+
1710
+ expect(
1711
+ me
1712
+ .fromAst(stateVariables["/d22"].stateValues.formula)
1713
+ .equals(me.fromText("cos(x+y^2)z")),
1714
+ ).eq(true);
1715
+ expect(stateVariables["/d22"].stateValues.variables).eqls(["x"]);
1716
+ expect(stateVariables["/d22"].stateValues.derivVariables).eqls(["x"]);
1717
+
1718
+ expect(
1719
+ me
1720
+ .fromAst(stateVariables["/d23"].stateValues.formula)
1721
+ .equals(me.fromText("cos(x+y^2)z")),
1722
+ ).eq(true);
1723
+ expect(stateVariables["/d23"].stateValues.variables).eqls([
1724
+ "z",
1725
+ "y",
1726
+ "x",
1727
+ ]);
1728
+ expect(stateVariables["/d23"].stateValues.derivVariables).eqls(["x"]);
1729
+
1730
+ expect(
1731
+ me
1732
+ .fromAst(stateVariables["/d24"].stateValues.formula)
1733
+ .equals(me.fromText("sin(x+y^2)")),
1734
+ ).eq(true);
1735
+ expect(stateVariables["/d24"].stateValues.variables).eqls([
1736
+ "z",
1737
+ "y",
1738
+ "x",
1739
+ ]);
1740
+ expect(stateVariables["/d24"].stateValues.derivVariables).eqls(["z"]);
1741
+
1742
+ expect(
1743
+ me
1744
+ .fromAst(stateVariables["/d25"].stateValues.formula)
1745
+ .equals(me.fromText("2 y cos(x+y^2)")),
1746
+ ).eq(true);
1747
+ expect(stateVariables["/d25"].stateValues.variables).eqls([
1748
+ "z",
1749
+ "y",
1750
+ "x",
1751
+ ]);
1752
+ expect(stateVariables["/d25"].stateValues.derivVariables).eqls([
1753
+ "y",
1754
+ "z",
1755
+ ]);
1756
+
1757
+ expect(
1758
+ me
1759
+ .fromAst(stateVariables["/d26"].stateValues.formula)
1760
+ .equals(me.fromText("-2 y cos(x+y^2)z")),
1761
+ ).eq(true);
1762
+ expect(stateVariables["/d26"].stateValues.variables).eqls([
1763
+ "z",
1764
+ "y",
1765
+ "x",
1766
+ ]);
1767
+ expect(stateVariables["/d26"].stateValues.derivVariables).eqls([
1768
+ "x",
1769
+ "x",
1770
+ "y",
1771
+ ]);
1772
+
1773
+ expect(
1774
+ me
1775
+ .fromAst(stateVariables["/d27"].stateValues.formula)
1776
+ .equals(me.fromText("0")),
1777
+ ).eq(true);
1778
+ expect(stateVariables["/d27"].stateValues.variables).eqls([
1779
+ "z",
1780
+ "y",
1781
+ "x",
1782
+ ]);
1783
+ expect(stateVariables["/d27"].stateValues.derivVariables).eqls(["u"]);
1784
+
1785
+ expect(
1786
+ me
1787
+ .fromAst(stateVariables["/d28"].stateValues.formula)
1788
+ .equals(me.fromText("-2 y cos(x+y^2)z")),
1789
+ ).eq(true);
1790
+ expect(stateVariables["/d28"].stateValues.variables).eqls(["z"]);
1791
+ expect(stateVariables["/d28"].stateValues.derivVariables).eqls([
1792
+ "x",
1793
+ "x",
1794
+ "y",
1795
+ ]);
1796
+
1797
+ expect(
1798
+ me
1799
+ .fromAst(stateVariables["/d31"].stateValues.formula)
1800
+ .equals(me.fromText("cos(x+y^2)z")),
1801
+ ).eq(true);
1802
+ expect(stateVariables["/d31"].stateValues.variables).eqls(["x", "y"]);
1803
+ expect(stateVariables["/d31"].stateValues.derivVariables).eqls(["x"]);
1804
+
1805
+ expect(
1806
+ me
1807
+ .fromAst(stateVariables["/d32"].stateValues.formula)
1808
+ .equals(me.fromText("sin(x+y^2)")),
1809
+ ).eq(true);
1810
+ expect(stateVariables["/d32"].stateValues.variables).eqls(["z"]);
1811
+ expect(stateVariables["/d32"].stateValues.derivVariables).eqls(["z"]);
1812
+
1813
+ expect(
1814
+ me
1815
+ .fromAst(stateVariables["/d33"].stateValues.formula)
1816
+ .equals(me.fromText("cos(x+y^2)z")),
1817
+ ).eq(true);
1818
+ expect(stateVariables["/d33"].stateValues.variables).eqls(["x", "y"]);
1819
+ expect(stateVariables["/d33"].stateValues.derivVariables).eqls(["x"]);
1820
+
1821
+ expect(
1822
+ me
1823
+ .fromAst(stateVariables["/d34"].stateValues.formula)
1824
+ .equals(me.fromText("sin(x+y^2)")),
1825
+ ).eq(true);
1826
+ expect(stateVariables["/d34"].stateValues.variables).eqls(["x", "y"]);
1827
+ expect(stateVariables["/d34"].stateValues.derivVariables).eqls(["z"]);
1828
+
1829
+ expect(
1830
+ me
1831
+ .fromAst(stateVariables["/d35"].stateValues.formula)
1832
+ .equals(me.fromText("2 y cos(x+y^2)")),
1833
+ ).eq(true);
1834
+ expect(stateVariables["/d35"].stateValues.variables).eqls(["x", "y"]);
1835
+ expect(stateVariables["/d35"].stateValues.derivVariables).eqls([
1836
+ "y",
1837
+ "z",
1838
+ ]);
1839
+
1840
+ expect(
1841
+ me
1842
+ .fromAst(stateVariables["/d36"].stateValues.formula)
1843
+ .equals(me.fromText("-2 y cos(x+y^2)z")),
1844
+ ).eq(true);
1845
+ expect(stateVariables["/d36"].stateValues.variables).eqls(["x", "y"]);
1846
+ expect(stateVariables["/d36"].stateValues.derivVariables).eqls([
1847
+ "x",
1848
+ "x",
1849
+ "y",
1850
+ ]);
1851
+
1852
+ expect(
1853
+ me
1854
+ .fromAst(stateVariables["/d37"].stateValues.formula)
1855
+ .equals(me.fromText("0")),
1856
+ ).eq(true);
1857
+ expect(stateVariables["/d37"].stateValues.variables).eqls(["x", "y"]);
1858
+ expect(stateVariables["/d37"].stateValues.derivVariables).eqls(["u"]);
1859
+
1860
+ expect(
1861
+ me
1862
+ .fromAst(stateVariables["/d38"].stateValues.formula)
1863
+ .equals(me.fromText("-2 y cos(x+y^2)z")),
1864
+ ).eq(true);
1865
+ expect(stateVariables["/d38"].stateValues.variables).eqls(["z"]);
1866
+ expect(stateVariables["/d38"].stateValues.derivVariables).eqls([
1867
+ "x",
1868
+ "x",
1869
+ "y",
1870
+ ]);
1871
+
1872
+ expect(
1873
+ me
1874
+ .fromAst(stateVariables["/d41"].stateValues.formula)
1875
+ .equals(me.fromText("cos(x_1+x_2^2)x_3")),
1876
+ ).eq(true);
1877
+ expect(stateVariables["/d41"].stateValues.variables).eqls([
1878
+ ["_", "x", 1],
1879
+ ["_", "x", 2],
1880
+ ["_", "x", 3],
1881
+ ]);
1882
+ expect(stateVariables["/d41"].stateValues.derivVariables).eqls([
1883
+ ["_", "x", 1],
1884
+ ]);
1885
+
1886
+ expect(
1887
+ me
1888
+ .fromAst(stateVariables["/d42"].stateValues.formula)
1889
+ .equals(me.fromText("-2 x_2 sin(x_1+x_2^2)")),
1890
+ ).eq(true);
1891
+ expect(stateVariables["/d42"].stateValues.variables).eqls([
1892
+ ["_", "x", 1],
1893
+ ["_", "x", 2],
1894
+ ["_", "x", 3],
1895
+ ]);
1896
+ expect(stateVariables["/d42"].stateValues.derivVariables).eqls([
1897
+ ["_", "x", 1],
1898
+ ["_", "x", 2],
1899
+ ["_", "x", 3],
1900
+ ]);
1901
+
1902
+ expect(
1903
+ me
1904
+ .fromAst(stateVariables["/d43"].stateValues.formula)
1905
+ .equals(me.fromText("0")),
1906
+ ).eq(true);
1907
+ expect(stateVariables["/d43"].stateValues.variables).eqls([
1908
+ ["_", "x", 1],
1909
+ ["_", "x", 2],
1910
+ ["_", "x", 3],
1911
+ ]);
1912
+ expect(stateVariables["/d43"].stateValues.derivVariables).eqls(["x"]);
1913
+
1914
+ expect(
1915
+ me
1916
+ .fromAst(stateVariables["/d44"].stateValues.formula)
1917
+ .equals(me.fromText("-2 x_2 sin(x_1+x_2^2)")),
1918
+ ).eq(true);
1919
+ expect(stateVariables["/d44"].stateValues.variables).eqls([
1920
+ ["_", "x", 3],
1921
+ ["_", "x", 2],
1922
+ ["_", "x", 1],
1923
+ ]);
1924
+ expect(stateVariables["/d44"].stateValues.derivVariables).eqls([
1925
+ ["_", "x", 1],
1926
+ ["_", "x", 2],
1927
+ ["_", "x", 3],
1928
+ ]);
1929
+ });
1930
+ });
1931
+
1932
+ it("specifying derivative variables of an expression", () => {
1933
+ cy.window().then(async (win) => {
1934
+ win.postMessage(
1935
+ {
1936
+ doenetML: `
1937
+ <text>a</text>
1938
+ <math name="m1">sin(x+y^2)z</math>
1939
+ <math name="m2">sin(x_1+x_2^2)x_3</math>
1940
+ <derivative name="d1">$m1</derivative>
1941
+ <derivative name="d2" variable="x">$m1</derivative>
1942
+ <derivative name="d3" variables="x y z">$m1</derivative>
1943
+ <derivative name="d4" variables="z y x">$m1</derivative>
1944
+ <derivative name="d5" derivVariables="x">$m1</derivative>
1945
+ <derivative name="d5a" derivVariable="x" variables="x y z">$m1</derivative>
1946
+ <derivative name="d6" derivVariables="x x">$m1</derivative>
1947
+ <derivative name="d6a" derivVariable="x"><derivative derivVariable="x">$m1</derivative></derivative>
1948
+ <derivative name="d6b" derivVariables="x" variables="x y z"><derivative derivVariables="x">$m1</derivative></derivative>
1949
+ <derivative name="d6c" derivVariables="x"><derivative derivVariable="x" variables="x y z">$m1</derivative></derivative>
1950
+ <derivative name="d6d" derivVariables="x x" variables="x y z">$m1</derivative>
1951
+ <derivative name="d7" derivVariables="x y">$m1</derivative>
1952
+ <derivative name="d7a" derivVariable="y"><derivative derivVariables="x">$m1</derivative></derivative>
1953
+ <derivative name="d7b" derivVariables="y" variables="x y z"><derivative derivVariable="x">$m1</derivative></derivative>
1954
+ <derivative name="d7c" derivVariable="y"><derivative derivVariables="x" variables="x y z">$m1</derivative></derivative>
1955
+ <derivative name="d8" derivVariables="x y z">$m1</derivative>
1956
+ <derivative name="d8a" derivVariables="z"><derivative derivVariable="y"><derivative derivVariables="x">$m1</derivative></derivative></derivative>
1957
+ <derivative name="d8b" derivVariable="z" variables="x y z"><derivative derivVariables="y"><derivative derivVariable="x">$m1</derivative></derivative></derivative>
1958
+ <derivative name="d8c" derivVariables="z"><derivative derivVariable="y"><derivative derivVariables="x" variables="x y z">$m1</derivative></derivative></derivative>
1959
+ <derivative name="d9" derivVariables="x y z x">$m1</derivative>
1960
+ <derivative name="d9a" derivVariables="x"><derivative derivVariables="z"><derivative derivVariables="y"><derivative derivVariables="x">$m1</derivative></derivative></derivative></derivative>
1961
+ <derivative name="d9b" derivVariable="x"><derivative derivVariable="z" variables="x y z"><derivative derivVariable="y"><derivative derivVariables="x">$m1</derivative></derivative></derivative></derivative>
1962
+ <derivative name="d9c" derivVariable="x"><derivative derivVariables="z"><derivative derivVariables="y" variables="x y z"><derivative derivVariables="x">$m1</derivative></derivative></derivative></derivative>
1963
+ <derivative name="d10" derivVariables="q">$m1</derivative>
1964
+ <derivative name="d11" derivVariable="y" variables="x y z">$m1</derivative>
1965
+ <derivative name="d12" derivVariables="y" variables="x z">$m1</derivative>
1966
+
1967
+
1968
+ <derivative name="d13" variables="x_1 x_2 x_3">$m2</derivative>
1969
+ <derivative name="d14" derivVariables="x_1 x_1">$m2</derivative>
1970
+ <derivative name="d15" derivVariables="x_1 x_1" variables="x_1 x_2 x_3">$m2</derivative>
1971
+
1972
+ `,
1973
+ },
1974
+ "*",
1975
+ );
1976
+ });
1977
+
1978
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
1979
+
1980
+ cy.window().then(async (win) => {
1981
+ let stateVariables = await win.returnAllStateVariables1();
1982
+
1983
+ expect(
1984
+ me
1985
+ .fromAst(stateVariables["/d1"].stateValues.formula)
1986
+ .equals(me.fromText("cos(x+y^2)z")),
1987
+ ).eq(true);
1988
+ expect(stateVariables["/d1"].stateValues.variables).eqls(["x"]);
1989
+ expect(stateVariables["/d1"].stateValues.derivVariables).eqls(["x"]);
1990
+
1991
+ expect(
1992
+ me
1993
+ .fromAst(stateVariables["/d2"].stateValues.formula)
1994
+ .equals(me.fromText("cos(x+y^2)z")),
1995
+ ).eq(true);
1996
+ expect(stateVariables["/d2"].stateValues.variables).eqls(["x"]);
1997
+ expect(stateVariables["/d2"].stateValues.derivVariables).eqls(["x"]);
1998
+
1999
+ expect(
2000
+ me
2001
+ .fromAst(stateVariables["/d3"].stateValues.formula)
2002
+ .equals(me.fromText("cos(x+y^2)z")),
2003
+ ).eq(true);
2004
+ expect(stateVariables["/d3"].stateValues.variables).eqls(["x", "y", "z"]);
2005
+ expect(stateVariables["/d3"].stateValues.derivVariables).eqls(["x"]);
2006
+
2007
+ expect(
2008
+ me
2009
+ .fromAst(stateVariables["/d4"].stateValues.formula)
2010
+ .equals(me.fromText("sin(x+y^2)")),
2011
+ ).eq(true);
2012
+ expect(stateVariables["/d4"].stateValues.variables).eqls(["z", "y", "x"]);
2013
+ expect(stateVariables["/d4"].stateValues.derivVariables).eqls(["z"]);
2014
+
2015
+ expect(
2016
+ me
2017
+ .fromAst(stateVariables["/d5"].stateValues.formula)
2018
+ .equals(me.fromText("cos(x+y^2)z")),
2019
+ ).eq(true);
2020
+ expect(stateVariables["/d5"].stateValues.variables).eqls(["x"]);
2021
+ expect(stateVariables["/d5"].stateValues.derivVariables).eqls(["x"]);
2022
+
2023
+ expect(
2024
+ me
2025
+ .fromAst(stateVariables["/d5a"].stateValues.formula)
2026
+ .equals(me.fromText("cos(x+y^2)z")),
2027
+ ).eq(true);
2028
+ expect(stateVariables["/d5a"].stateValues.variables).eqls([
2029
+ "x",
2030
+ "y",
2031
+ "z",
2032
+ ]);
2033
+ expect(stateVariables["/d5a"].stateValues.derivVariables).eqls(["x"]);
2034
+
2035
+ expect(
2036
+ me
2037
+ .fromAst(stateVariables["/d6"].stateValues.formula)
2038
+ .equals(me.fromText("-sin(x+y^2)z")),
2039
+ ).eq(true);
2040
+ expect(stateVariables["/d6"].stateValues.variables).eqls(["x"]);
2041
+ expect(stateVariables["/d6"].stateValues.derivVariables).eqls(["x", "x"]);
2042
+
2043
+ expect(
2044
+ me
2045
+ .fromAst(stateVariables["/d6a"].stateValues.formula)
2046
+ .equals(me.fromText("-sin(x+y^2)z")),
2047
+ ).eq(true);
2048
+ expect(stateVariables["/d6a"].stateValues.variables).eqls(["x"]);
2049
+ expect(stateVariables["/d6a"].stateValues.derivVariables).eqls(["x"]);
2050
+
2051
+ expect(
2052
+ me
2053
+ .fromAst(stateVariables["/d6b"].stateValues.formula)
2054
+ .equals(me.fromText("-sin(x+y^2)z")),
2055
+ ).eq(true);
2056
+ expect(stateVariables["/d6b"].stateValues.variables).eqls([
2057
+ "x",
2058
+ "y",
2059
+ "z",
2060
+ ]);
2061
+ expect(stateVariables["/d6b"].stateValues.derivVariables).eqls(["x"]);
2062
+
2063
+ expect(
2064
+ me
2065
+ .fromAst(stateVariables["/d6c"].stateValues.formula)
2066
+ .equals(me.fromText("-sin(x+y^2)z")),
2067
+ ).eq(true);
2068
+ expect(stateVariables["/d6c"].stateValues.variables).eqls([
2069
+ "x",
2070
+ "y",
2071
+ "z",
2072
+ ]);
2073
+ expect(stateVariables["/d6c"].stateValues.derivVariables).eqls(["x"]);
2074
+
2075
+ expect(
2076
+ me
2077
+ .fromAst(stateVariables["/d6d"].stateValues.formula)
2078
+ .equals(me.fromText("-sin(x+y^2)z")),
2079
+ ).eq(true);
2080
+ expect(stateVariables["/d6d"].stateValues.variables).eqls([
2081
+ "x",
2082
+ "y",
2083
+ "z",
2084
+ ]);
2085
+ expect(stateVariables["/d6d"].stateValues.derivVariables).eqls([
2086
+ "x",
2087
+ "x",
2088
+ ]);
2089
+
2090
+ expect(
2091
+ me
2092
+ .fromAst(stateVariables["/d7"].stateValues.formula)
2093
+ .equals(me.fromText("-2 y sin(x+y^2)z")),
2094
+ ).eq(true);
2095
+ expect(stateVariables["/d7"].stateValues.variables).eqls(["x", "y"]);
2096
+ expect(stateVariables["/d7"].stateValues.derivVariables).eqls(["x", "y"]);
2097
+
2098
+ expect(
2099
+ me
2100
+ .fromAst(stateVariables["/d7a"].stateValues.formula)
2101
+ .equals(me.fromText("-2 y sin(x+y^2)z")),
2102
+ ).eq(true);
2103
+ expect(stateVariables["/d7a"].stateValues.variables).eqls(["x"]);
2104
+ expect(stateVariables["/d7a"].stateValues.derivVariables).eqls(["y"]);
2105
+
2106
+ expect(
2107
+ me
2108
+ .fromAst(stateVariables["/d7b"].stateValues.formula)
2109
+ .equals(me.fromText("-2 y sin(x+y^2)z")),
2110
+ ).eq(true);
2111
+ expect(stateVariables["/d7b"].stateValues.variables).eqls([
2112
+ "x",
2113
+ "y",
2114
+ "z",
2115
+ ]);
2116
+ expect(stateVariables["/d7b"].stateValues.derivVariables).eqls(["y"]);
2117
+
2118
+ expect(
2119
+ me
2120
+ .fromAst(stateVariables["/d7c"].stateValues.formula)
2121
+ .equals(me.fromText("-2 y sin(x+y^2)z")),
2122
+ ).eq(true);
2123
+ expect(stateVariables["/d7c"].stateValues.variables).eqls([
2124
+ "x",
2125
+ "y",
2126
+ "z",
2127
+ ]);
2128
+ expect(stateVariables["/d7c"].stateValues.derivVariables).eqls(["y"]);
2129
+
2130
+ expect(
2131
+ me
2132
+ .fromAst(stateVariables["/d8"].stateValues.formula)
2133
+ .equals(me.fromText("-2 y sin(x+y^2)")),
2134
+ ).eq(true);
2135
+ expect(stateVariables["/d8"].stateValues.variables).eqls(["x", "y", "z"]);
2136
+ expect(stateVariables["/d8"].stateValues.derivVariables).eqls([
2137
+ "x",
2138
+ "y",
2139
+ "z",
2140
+ ]);
2141
+
2142
+ expect(
2143
+ me
2144
+ .fromAst(stateVariables["/d8a"].stateValues.formula)
2145
+ .equals(me.fromText("-2 y sin(x+y^2)")),
2146
+ ).eq(true);
2147
+ expect(stateVariables["/d8a"].stateValues.variables).eqls(["x"]);
2148
+ expect(stateVariables["/d8a"].stateValues.derivVariables).eqls(["z"]);
2149
+
2150
+ expect(
2151
+ me
2152
+ .fromAst(stateVariables["/d8b"].stateValues.formula)
2153
+ .equals(me.fromText("-2 y sin(x+y^2)")),
2154
+ ).eq(true);
2155
+ expect(stateVariables["/d8b"].stateValues.variables).eqls([
2156
+ "x",
2157
+ "y",
2158
+ "z",
2159
+ ]);
2160
+ expect(stateVariables["/d8b"].stateValues.derivVariables).eqls(["z"]);
2161
+
2162
+ expect(
2163
+ me
2164
+ .fromAst(stateVariables["/d8c"].stateValues.formula)
2165
+ .equals(me.fromText("-2 y sin(x+y^2)")),
2166
+ ).eq(true);
2167
+ expect(stateVariables["/d8c"].stateValues.variables).eqls([
2168
+ "x",
2169
+ "y",
2170
+ "z",
2171
+ ]);
2172
+ expect(stateVariables["/d8c"].stateValues.derivVariables).eqls(["z"]);
2173
+
2174
+ expect(
2175
+ me
2176
+ .fromAst(stateVariables["/d9"].stateValues.formula)
2177
+ .equals(me.fromText("-2 y cos(x+y^2)")),
2178
+ ).eq(true);
2179
+ expect(stateVariables["/d9"].stateValues.variables).eqls(["x", "y", "z"]);
2180
+ expect(stateVariables["/d9"].stateValues.derivVariables).eqls([
2181
+ "x",
2182
+ "y",
2183
+ "z",
2184
+ "x",
2185
+ ]);
2186
+
2187
+ expect(
2188
+ me
2189
+ .fromAst(stateVariables["/d9a"].stateValues.formula)
2190
+ .equals(me.fromText("-2 y cos(x+y^2)")),
2191
+ ).eq(true);
2192
+ expect(stateVariables["/d9a"].stateValues.variables).eqls(["x"]);
2193
+ expect(stateVariables["/d9a"].stateValues.derivVariables).eqls(["x"]);
2194
+
2195
+ expect(
2196
+ me
2197
+ .fromAst(stateVariables["/d9b"].stateValues.formula)
2198
+ .equals(me.fromText("-2 y cos(x+y^2)")),
2199
+ ).eq(true);
2200
+ expect(stateVariables["/d9b"].stateValues.variables).eqls([
2201
+ "x",
2202
+ "y",
2203
+ "z",
2204
+ ]);
2205
+ expect(stateVariables["/d9b"].stateValues.derivVariables).eqls(["x"]);
2206
+
2207
+ expect(
2208
+ me
2209
+ .fromAst(stateVariables["/d9c"].stateValues.formula)
2210
+ .equals(me.fromText("-2 y cos(x+y^2)")),
2211
+ ).eq(true);
2212
+ expect(stateVariables["/d9c"].stateValues.variables).eqls([
2213
+ "x",
2214
+ "y",
2215
+ "z",
2216
+ ]);
2217
+ expect(stateVariables["/d9c"].stateValues.derivVariables).eqls(["x"]);
2218
+
2219
+ expect(
2220
+ me
2221
+ .fromAst(stateVariables["/d10"].stateValues.formula)
2222
+ .equals(me.fromText("0")),
2223
+ ).eq(true);
2224
+ expect(stateVariables["/d10"].stateValues.variables).eqls(["q"]);
2225
+ expect(stateVariables["/d10"].stateValues.derivVariables).eqls(["q"]);
2226
+
2227
+ expect(
2228
+ me
2229
+ .fromAst(stateVariables["/d11"].stateValues.formula)
2230
+ .equals(me.fromText("2 y cos(x+y^2)z")),
2231
+ ).eq(true);
2232
+ expect(stateVariables["/d11"].stateValues.variables).eqls([
2233
+ "x",
2234
+ "y",
2235
+ "z",
2236
+ ]);
2237
+ expect(stateVariables["/d11"].stateValues.derivVariables).eqls(["y"]);
2238
+
2239
+ expect(
2240
+ me
2241
+ .fromAst(stateVariables["/d12"].stateValues.formula)
2242
+ .equals(me.fromText("2 y cos(x+y^2)z")),
2243
+ ).eq(true);
2244
+ expect(stateVariables["/d12"].stateValues.variables).eqls(["x", "z"]);
2245
+ expect(stateVariables["/d12"].stateValues.derivVariables).eqls(["y"]);
2246
+
2247
+ expect(
2248
+ me
2249
+ .fromAst(stateVariables["/d13"].stateValues.formula)
2250
+ .equals(me.fromText("cos(x_1+x_2^2)x_3")),
2251
+ ).eq(true);
2252
+ expect(stateVariables["/d13"].stateValues.variables).eqls([
2253
+ ["_", "x", 1],
2254
+ ["_", "x", 2],
2255
+ ["_", "x", 3],
2256
+ ]);
2257
+ expect(stateVariables["/d13"].stateValues.derivVariables).eqls([
2258
+ ["_", "x", 1],
2259
+ ]);
2260
+
2261
+ expect(
2262
+ me
2263
+ .fromAst(stateVariables["/d14"].stateValues.formula)
2264
+ .equals(me.fromText("-sin(x_1+x_2^2)x_3")),
2265
+ ).eq(true);
2266
+ expect(stateVariables["/d14"].stateValues.variables).eqls([
2267
+ ["_", "x", 1],
2268
+ ]);
2269
+ expect(stateVariables["/d14"].stateValues.derivVariables).eqls([
2270
+ ["_", "x", 1],
2271
+ ["_", "x", 1],
2272
+ ]);
2273
+
2274
+ expect(
2275
+ me
2276
+ .fromAst(stateVariables["/d15"].stateValues.formula)
2277
+ .equals(me.fromText("-sin(x_1+x_2^2)x_3")),
2278
+ ).eq(true);
2279
+ expect(stateVariables["/d15"].stateValues.variables).eqls([
2280
+ ["_", "x", 1],
2281
+ ["_", "x", 2],
2282
+ ["_", "x", 3],
2283
+ ]);
2284
+ expect(stateVariables["/d15"].stateValues.derivVariables).eqls([
2285
+ ["_", "x", 1],
2286
+ ["_", "x", 1],
2287
+ ]);
2288
+ });
2289
+ });
2290
+
2291
+ it("derivative of function with changed variables", () => {
2292
+ cy.window().then(async (win) => {
2293
+ win.postMessage(
2294
+ {
2295
+ doenetML: `
2296
+ <text>a</text>
2297
+ <function name="f1" variables="x y z">sin(x+y^2)z</function>
2298
+ <function name="f2" variables="z y x">$f1</function>
2299
+ <function name="g1" variables="x_1 x_2 x_3">sin(x_1+x_2^2)x_3</function>
2300
+ <function name="g2" variables="x_3 x_2 x_1">$g1</function>
2301
+ <derivative name="df1">$f1</derivative>
2302
+ <derivative name="d2f1">$df1</derivative>
2303
+ <derivative name="df2">$f2</derivative>
2304
+ <derivative name="d2f2">$df2</derivative>
2305
+ <derivative name="dg1">$g1</derivative>
2306
+ <derivative name="d2g1">$dg1</derivative>
2307
+ <derivative name="dg2">$g2</derivative>
2308
+ <derivative name="d2g2">$dg2</derivative>
2309
+
2310
+ `,
2311
+ },
2312
+ "*",
2313
+ );
2314
+ });
2315
+
2316
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
2317
+
2318
+ cy.window().then(async (win) => {
2319
+ let stateVariables = await win.returnAllStateVariables1();
2320
+
2321
+ expect(
2322
+ me
2323
+ .fromAst(stateVariables["/df1"].stateValues.formula)
2324
+ .equals(me.fromText("cos(x+y^2)z")),
2325
+ ).eq(true);
2326
+ expect(stateVariables["/df1"].stateValues.variables).eqls([
2327
+ "x",
2328
+ "y",
2329
+ "z",
2330
+ ]);
2331
+ expect(stateVariables["/df1"].stateValues.derivVariables).eqls(["x"]);
2332
+
2333
+ expect(
2334
+ me
2335
+ .fromAst(stateVariables["/df2"].stateValues.formula)
2336
+ .equals(me.fromText("sin(x+y^2)")),
2337
+ ).eq(true);
2338
+ expect(stateVariables["/df2"].stateValues.variables).eqls([
2339
+ "z",
2340
+ "y",
2341
+ "x",
2342
+ ]);
2343
+ expect(stateVariables["/df2"].stateValues.derivVariables).eqls(["z"]);
2344
+
2345
+ expect(
2346
+ me
2347
+ .fromAst(stateVariables["/dg1"].stateValues.formula)
2348
+ .equals(me.fromText("cos(x_1+x_2^2)x_3")),
2349
+ ).eq(true);
2350
+ expect(stateVariables["/dg1"].stateValues.variables).eqls([
2351
+ ["_", "x", 1],
2352
+ ["_", "x", 2],
2353
+ ["_", "x", 3],
2354
+ ]);
2355
+ expect(stateVariables["/dg1"].stateValues.derivVariables).eqls([
2356
+ ["_", "x", 1],
2357
+ ]);
2358
+
2359
+ expect(
2360
+ me
2361
+ .fromAst(stateVariables["/dg2"].stateValues.formula)
2362
+ .equals(me.fromText("sin(x_1+x_2^2)")),
2363
+ ).eq(true);
2364
+ expect(stateVariables["/dg2"].stateValues.variables).eqls([
2365
+ ["_", "x", 3],
2366
+ ["_", "x", 2],
2367
+ ["_", "x", 1],
2368
+ ]);
2369
+ expect(stateVariables["/dg2"].stateValues.derivVariables).eqls([
2370
+ ["_", "x", 3],
2371
+ ]);
2372
+ });
2373
+ });
2374
+
2375
+ it("derivative of function with changed variables, convert to single variable function", () => {
2376
+ cy.window().then(async (win) => {
2377
+ win.postMessage(
2378
+ {
2379
+ doenetML: `
2380
+ <text>a</text>
2381
+ <function name="f1" variables="x y z">sin(x)z</function>
2382
+ <function name="f2" variables="z y x">$f1.formula</function>
2383
+ <function name="f3" variables="x y z">sin(x)yz</function>
2384
+ <function name="f4" variables="z y x">$f3.formula</function>
2385
+
2386
+ <derivative derivvariables="z" name="df1" >$f1</derivative>
2387
+ <derivative name="df2">$f2</derivative>
2388
+ <function variable="x" name="df2a">$df2.formula</function>
2389
+ <derivative derivvariables="z y" name="df3zy">$f3</derivative>
2390
+ <derivative derivvariable="y" name="df3y">$f3</derivative>
2391
+ <derivative derivvariables="z" name="df3zya">$df3y</derivative>
2392
+ <derivative derivvariables="z y" name="df4zy">$f4</derivative>
2393
+ <derivative name="df4z">$f4</derivative>
2394
+ <derivative derivvariable="y" name="df4yz">$df4z</derivative>
2395
+ <function variables="x" name="df4zya">$df4zy.formula</function>
2396
+ <function variable="x" name="df4yza">$df4yz.formula</function>
2397
+
2398
+ <graph>
2399
+ $df2a
2400
+ </graph>
2401
+
2402
+ <graph>
2403
+ $df4zya
2404
+ </graph>
2405
+
2406
+ <graph>
2407
+ $df4yza
2408
+ </graph>
2409
+
2410
+ <map assignNames="t1 t2 t3">
2411
+ <template newNamespace>
2412
+ <p><aslist>
2413
+ <evaluate function="$(../df1)" input="$v 0 0" name="df1" />
2414
+ <evaluate function="$(../df2a)" input="$v" name="df2a" />
2415
+ <evaluate function="$(../df3zy)" input="$v 0 0" name="df3zy" />
2416
+ <evaluate function="$(../df3zya)" input="$v 0 0" name="df3zya" />
2417
+ <evaluate function="$(../df4zya)" input="$v" name="df4zya" />
2418
+ <evaluate function="$(../df4yza)" input="$v" name="df4yza" />
2419
+ <evaluate forceNumeric displayDigits="3" function="$(../df1)" input="$v 0 0" name="df1n" />
2420
+ <evaluate forceNumeric displayDigits="3" function="$(../df2a)" input="$v" name="df2an" />
2421
+ <evaluate forceNumeric displayDigits="3" function="$(../df3zy)" input="$v 0 0" name="df3zyn" />
2422
+ <evaluate forceNumeric displayDigits="3" function="$(../df3zya)" input="$v 0 0" name="df3zyan" />
2423
+ <evaluate forceNumeric displayDigits="3" function="$(../df4zya)" input="$v" name="df4zyan" />
2424
+ <evaluate forceNumeric displayDigits="3" function="$(../df4yza)" input="$v" name="df4yzan" />
2425
+ </aslist></p>
2426
+ </template>
2427
+ <sources alias="v"><sequence from="-2" to="2" step="2" /></sources>
2428
+ </map>
2429
+ `,
2430
+ },
2431
+ "*",
2432
+ );
2433
+ });
2434
+
2435
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
2436
+
2437
+ cy.window().then(async (win) => {
2438
+ let stateVariables = await win.returnAllStateVariables1();
2439
+
2440
+ expect(
2441
+ me
2442
+ .fromAst(stateVariables["/df1"].stateValues.formula)
2443
+ .equals(me.fromText("sin(x)")),
2444
+ ).eq(true);
2445
+ expect(stateVariables["/df1"].stateValues.variables).eqls([
2446
+ "x",
2447
+ "y",
2448
+ "z",
2449
+ ]);
2450
+ expect(stateVariables["/df1"].stateValues.derivVariables).eqls(["z"]);
2451
+
2452
+ expect(
2453
+ me
2454
+ .fromAst(stateVariables["/df2"].stateValues.formula)
2455
+ .equals(me.fromText("sin(x)")),
2456
+ ).eq(true);
2457
+ expect(stateVariables["/df2"].stateValues.variables).eqls([
2458
+ "z",
2459
+ "y",
2460
+ "x",
2461
+ ]);
2462
+ expect(stateVariables["/df2"].stateValues.derivVariables).eqls(["z"]);
2463
+
2464
+ expect(
2465
+ me
2466
+ .fromAst(stateVariables["/df2a"].stateValues.formula)
2467
+ .equals(me.fromText("sin(x)")),
2468
+ ).eq(true);
2469
+ expect(stateVariables["/df2a"].stateValues.variables).eqls(["x"]);
2470
+
2471
+ expect(
2472
+ me
2473
+ .fromAst(stateVariables["/df3zy"].stateValues.formula)
2474
+ .equals(me.fromText("sin(x)")),
2475
+ ).eq(true);
2476
+ expect(stateVariables["/df3zy"].stateValues.variables).eqls([
2477
+ "x",
2478
+ "y",
2479
+ "z",
2480
+ ]);
2481
+ expect(stateVariables["/df3zy"].stateValues.derivVariables).eqls([
2482
+ "z",
2483
+ "y",
2484
+ ]);
2485
+
2486
+ expect(
2487
+ me
2488
+ .fromAst(stateVariables["/df3y"].stateValues.formula)
2489
+ .equals(me.fromText("sin(x)z")),
2490
+ ).eq(true);
2491
+ expect(stateVariables["/df3y"].stateValues.variables).eqls([
2492
+ "x",
2493
+ "y",
2494
+ "z",
2495
+ ]);
2496
+ expect(stateVariables["/df3y"].stateValues.derivVariables).eqls(["y"]);
2497
+
2498
+ expect(
2499
+ me
2500
+ .fromAst(stateVariables["/df3zya"].stateValues.formula)
2501
+ .equals(me.fromText("sin(x)")),
2502
+ ).eq(true);
2503
+ expect(stateVariables["/df3zya"].stateValues.variables).eqls([
2504
+ "x",
2505
+ "y",
2506
+ "z",
2507
+ ]);
2508
+ expect(stateVariables["/df3zya"].stateValues.derivVariables).eqls(["z"]);
2509
+
2510
+ expect(
2511
+ me
2512
+ .fromAst(stateVariables["/df4zy"].stateValues.formula)
2513
+ .equals(me.fromText("sin(x)")),
2514
+ ).eq(true);
2515
+ expect(stateVariables["/df4zy"].stateValues.variables).eqls([
2516
+ "z",
2517
+ "y",
2518
+ "x",
2519
+ ]);
2520
+ expect(stateVariables["/df4zy"].stateValues.derivVariables).eqls([
2521
+ "z",
2522
+ "y",
2523
+ ]);
2524
+
2525
+ expect(
2526
+ me
2527
+ .fromAst(stateVariables["/df4z"].stateValues.formula)
2528
+ .equals(me.fromText("sin(x)y")),
2529
+ ).eq(true);
2530
+ expect(stateVariables["/df4z"].stateValues.variables).eqls([
2531
+ "z",
2532
+ "y",
2533
+ "x",
2534
+ ]);
2535
+ expect(stateVariables["/df4z"].stateValues.derivVariables).eqls(["z"]);
2536
+
2537
+ expect(
2538
+ me
2539
+ .fromAst(stateVariables["/df4yz"].stateValues.formula)
2540
+ .equals(me.fromText("sin(x)")),
2541
+ ).eq(true);
2542
+ expect(stateVariables["/df4yz"].stateValues.variables).eqls([
2543
+ "z",
2544
+ "y",
2545
+ "x",
2546
+ ]);
2547
+ expect(stateVariables["/df4yz"].stateValues.derivVariables).eqls(["y"]);
2548
+
2549
+ expect(
2550
+ me
2551
+ .fromAst(stateVariables["/df4zya"].stateValues.formula)
2552
+ .equals(me.fromText("sin(x)")),
2553
+ ).eq(true);
2554
+ expect(stateVariables["/df4zya"].stateValues.variables).eqls(["x"]);
2555
+
2556
+ expect(
2557
+ me
2558
+ .fromAst(stateVariables["/df4yza"].stateValues.formula)
2559
+ .equals(me.fromText("sin(x)")),
2560
+ ).eq(true);
2561
+ expect(stateVariables["/df4yza"].stateValues.variables).eqls(["x"]);
2562
+
2563
+ expect(stateVariables["/t1/df1"].stateValues.value).eqls([
2564
+ "apply",
2565
+ "sin",
2566
+ -2,
2567
+ ]);
2568
+ expect(stateVariables["/t1/df2a"].stateValues.value).eqls([
2569
+ "apply",
2570
+ "sin",
2571
+ -2,
2572
+ ]);
2573
+ expect(stateVariables["/t1/df3zy"].stateValues.value).eqls([
2574
+ "apply",
2575
+ "sin",
2576
+ -2,
2577
+ ]);
2578
+ expect(stateVariables["/t1/df3zya"].stateValues.value).eqls([
2579
+ "apply",
2580
+ "sin",
2581
+ -2,
2582
+ ]);
2583
+ expect(stateVariables["/t1/df4zya"].stateValues.value).eqls([
2584
+ "apply",
2585
+ "sin",
2586
+ -2,
2587
+ ]);
2588
+ expect(stateVariables["/t1/df4yza"].stateValues.value).eqls([
2589
+ "apply",
2590
+ "sin",
2591
+ -2,
2592
+ ]);
2593
+ expect(stateVariables["/t1/df1n"].stateValues.value).closeTo(
2594
+ Math.sin(-2),
2595
+ 1e-10,
2596
+ );
2597
+ expect(stateVariables["/t1/df2an"].stateValues.value).closeTo(
2598
+ Math.sin(-2),
2599
+ 1e-10,
2600
+ );
2601
+ expect(stateVariables["/t1/df3zyn"].stateValues.value).closeTo(
2602
+ Math.sin(-2),
2603
+ 1e-10,
2604
+ );
2605
+ expect(stateVariables["/t1/df3zyan"].stateValues.value).closeTo(
2606
+ Math.sin(-2),
2607
+ 1e-10,
2608
+ );
2609
+ expect(stateVariables["/t1/df4zyan"].stateValues.value).closeTo(
2610
+ Math.sin(-2),
2611
+ 1e-10,
2612
+ );
2613
+ expect(stateVariables["/t1/df4yzan"].stateValues.value).closeTo(
2614
+ Math.sin(-2),
2615
+ 1e-10,
2616
+ );
2617
+
2618
+ expect(stateVariables["/t2/df1"].stateValues.value).eq(0);
2619
+ expect(stateVariables["/t2/df2a"].stateValues.value).eq(0);
2620
+ expect(stateVariables["/t2/df3zy"].stateValues.value).eq(0);
2621
+ expect(stateVariables["/t2/df3zya"].stateValues.value).eq(0);
2622
+ expect(stateVariables["/t2/df4zya"].stateValues.value).eq(0);
2623
+ expect(stateVariables["/t2/df4yza"].stateValues.value).eq(0);
2624
+ expect(stateVariables["/t2/df1n"].stateValues.value).closeTo(0, 1e-10);
2625
+ expect(stateVariables["/t2/df2an"].stateValues.value).closeTo(0, 1e-10);
2626
+ expect(stateVariables["/t2/df3zyn"].stateValues.value).closeTo(0, 1e-10);
2627
+ expect(stateVariables["/t2/df3zyan"].stateValues.value).closeTo(0, 1e-10);
2628
+ expect(stateVariables["/t2/df4zyan"].stateValues.value).closeTo(0, 1e-10);
2629
+ expect(stateVariables["/t2/df4yzan"].stateValues.value).closeTo(0, 1e-10);
2630
+
2631
+ expect(stateVariables["/t3/df1"].stateValues.value).eqls([
2632
+ "apply",
2633
+ "sin",
2634
+ 2,
2635
+ ]);
2636
+ expect(stateVariables["/t3/df2a"].stateValues.value).eqls([
2637
+ "apply",
2638
+ "sin",
2639
+ 2,
2640
+ ]);
2641
+ expect(stateVariables["/t3/df3zy"].stateValues.value).eqls([
2642
+ "apply",
2643
+ "sin",
2644
+ 2,
2645
+ ]);
2646
+ expect(stateVariables["/t3/df3zya"].stateValues.value).eqls([
2647
+ "apply",
2648
+ "sin",
2649
+ 2,
2650
+ ]);
2651
+ expect(stateVariables["/t3/df4zya"].stateValues.value).eqls([
2652
+ "apply",
2653
+ "sin",
2654
+ 2,
2655
+ ]);
2656
+ expect(stateVariables["/t3/df4yza"].stateValues.value).eqls([
2657
+ "apply",
2658
+ "sin",
2659
+ 2,
2660
+ ]);
2661
+ expect(stateVariables["/t3/df1n"].stateValues.value).closeTo(
2662
+ Math.sin(2),
2663
+ 1e-10,
2664
+ );
2665
+ expect(stateVariables["/t3/df2an"].stateValues.value).closeTo(
2666
+ Math.sin(2),
2667
+ 1e-10,
2668
+ );
2669
+ expect(stateVariables["/t3/df3zyn"].stateValues.value).closeTo(
2670
+ Math.sin(2),
2671
+ 1e-10,
2672
+ );
2673
+ expect(stateVariables["/t3/df3zyan"].stateValues.value).closeTo(
2674
+ Math.sin(2),
2675
+ 1e-10,
2676
+ );
2677
+ expect(stateVariables["/t3/df4zyan"].stateValues.value).closeTo(
2678
+ Math.sin(2),
2679
+ 1e-10,
2680
+ );
2681
+ expect(stateVariables["/t3/df4yzan"].stateValues.value).closeTo(
2682
+ Math.sin(2),
2683
+ 1e-10,
2684
+ );
2685
+
2686
+ let df1 = createFunctionFromDefinition(
2687
+ stateVariables["/df1"].stateValues.fDefinitions[0],
2688
+ );
2689
+ let df2a = createFunctionFromDefinition(
2690
+ stateVariables["/df2a"].stateValues.fDefinitions[0],
2691
+ );
2692
+ let df3zy = createFunctionFromDefinition(
2693
+ stateVariables["/df3zy"].stateValues.fDefinitions[0],
2694
+ );
2695
+ let df3zya = createFunctionFromDefinition(
2696
+ stateVariables["/df3zya"].stateValues.fDefinitions[0],
2697
+ );
2698
+ let df4zya = createFunctionFromDefinition(
2699
+ stateVariables["/df4zya"].stateValues.fDefinitions[0],
2700
+ );
2701
+ let df4yza = createFunctionFromDefinition(
2702
+ stateVariables["/df4yza"].stateValues.fDefinitions[0],
2703
+ );
2704
+
2705
+ for (let i = 1; i <= 21; i++) {
2706
+ let x = 0.2 * (i - 11);
2707
+ expect(df1(x, 0, 0)).closeTo(Math.sin(x), 1e-10);
2708
+ expect(df2a(x)).closeTo(Math.sin(x), 1e-10);
2709
+ expect(df3zy(x, 0, 0)).closeTo(Math.sin(x), 1e-10);
2710
+ expect(df3zya(x, 0, 0)).closeTo(Math.sin(x), 1e-10);
2711
+ expect(df4zya(x)).closeTo(Math.sin(x), 1e-10);
2712
+ expect(df4yza(x)).closeTo(Math.sin(x), 1e-10);
2713
+ }
2714
+ });
2715
+ });
2716
+
2717
+ it("derivative with empty variables attribute", () => {
2718
+ cy.window().then(async (win) => {
2719
+ win.postMessage(
2720
+ {
2721
+ doenetML: `
2722
+ <text>a</text>
2723
+ <derivative name="d1" variables="">x^2</derivative>
2724
+
2725
+ <graph>
2726
+ $d1
2727
+ </graph>
2728
+ `,
2729
+ },
2730
+ "*",
2731
+ );
2732
+ });
2733
+
2734
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
2735
+
2736
+ cy.window().then(async (win) => {
2737
+ let stateVariables = await win.returnAllStateVariables1();
2738
+
2739
+ expect(
2740
+ me
2741
+ .fromAst(stateVariables["/d1"].stateValues.formula)
2742
+ .equals(me.fromText("2x")),
2743
+ ).eq(true);
2744
+ expect(stateVariables["/d1"].stateValues.variables).eqls(["x"]);
2745
+ expect(stateVariables["/d1"].stateValues.derivVariables).eqls(["x"]);
2746
+
2747
+ let d1 = createFunctionFromDefinition(
2748
+ stateVariables["/d1"].stateValues.fDefinitions[0],
2749
+ );
2750
+
2751
+ for (let i = 1; i <= 21; i++) {
2752
+ let x = 0.2 * (i - 11);
2753
+ expect(d1(x)).closeTo(2 * x, 1e-10);
2754
+ }
2755
+ });
2756
+ });
2757
+
2758
+ // check to make sure fixed bug where wasn't displaying inside <m>
2759
+ it("derivative displayed inside <m>", () => {
2760
+ cy.window().then(async (win) => {
2761
+ win.postMessage(
2762
+ {
2763
+ doenetML: `
2764
+ <text>a</text>
2765
+ <p>Let <m>f(x) = <function name="f">sin(x)</function></m>.
2766
+ Then <m>f'(x) = <derivative><copy target="f" /></derivative></m>.</p>
2767
+ `,
2768
+ },
2769
+ "*",
2770
+ );
2771
+ });
2772
+
2773
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
2774
+
2775
+ cy.get(cesc("#\\/_m1"))
2776
+ .find(".mjx-mrow")
2777
+ .eq(0)
2778
+ .invoke("text")
2779
+ .then((text) => {
2780
+ expect(text.trim()).equal("f(x)=sin(x)");
2781
+ });
2782
+
2783
+ cy.get(cesc("#\\/_m2"))
2784
+ .find(".mjx-mrow")
2785
+ .eq(0)
2786
+ .invoke("text")
2787
+ .then((text) => {
2788
+ expect(text.trim()).equal("f′(x)=cos(x)");
2789
+ });
2790
+ });
2791
+
2792
+ it("derivatives of interpolated function", () => {
2793
+ cy.window().then(async (win) => {
2794
+ win.postMessage(
2795
+ {
2796
+ doenetML: `
2797
+ <text>a</text>
2798
+ <graph>
2799
+ <function minima='(3,4)' />
2800
+ <derivative><copy target="_function1"/></derivative>
2801
+ <derivative><copy target="_derivative1"/></derivative>
2802
+ <derivative><copy target="_derivative2"/></derivative>
2803
+ <derivative><copy target="_derivative3"/></derivative>
2804
+ <derivative><copy target="_derivative4"/></derivative>
2805
+ <derivative><copy target="_derivative5"/></derivative>
2806
+ </graph>
2807
+ `,
2808
+ },
2809
+ "*",
2810
+ );
2811
+ });
2812
+
2813
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
2814
+
2815
+ cy.window().then(async (win) => {
2816
+ let stateVariables = await win.returnAllStateVariables1();
2817
+
2818
+ let f1 = createFunctionFromDefinition(
2819
+ stateVariables["/_function1"].stateValues.fDefinitions[0],
2820
+ );
2821
+ let d1 = createFunctionFromDefinition(
2822
+ stateVariables["/_derivative1"].stateValues.fDefinitions[0],
2823
+ );
2824
+ let d2 = createFunctionFromDefinition(
2825
+ stateVariables["/_derivative2"].stateValues.fDefinitions[0],
2826
+ );
2827
+ let d3 = createFunctionFromDefinition(
2828
+ stateVariables["/_derivative3"].stateValues.fDefinitions[0],
2829
+ );
2830
+ let d4 = createFunctionFromDefinition(
2831
+ stateVariables["/_derivative4"].stateValues.fDefinitions[0],
2832
+ );
2833
+ let d5 = createFunctionFromDefinition(
2834
+ stateVariables["/_derivative5"].stateValues.fDefinitions[0],
2835
+ );
2836
+ let d6 = createFunctionFromDefinition(
2837
+ stateVariables["/_derivative6"].stateValues.fDefinitions[0],
2838
+ );
2839
+
2840
+ for (let x = -10; x <= 10; x += 0.5) {
2841
+ expect(f1(x)).eq((x - 3) ** 2 + 4);
2842
+ expect(d1(x)).eq(2 * (x - 3));
2843
+ expect(d2(x)).eq(2);
2844
+ expect(d3(x)).eq(0);
2845
+ expect(d4(x)).eq(0);
2846
+ expect(d5(x)).eq(0);
2847
+ expect(d6(x)).eq(0);
2848
+ }
2849
+ });
2850
+ });
2851
+
2852
+ it("derivatives of interpolated function 2", () => {
2853
+ cy.window().then(async (win) => {
2854
+ win.postMessage(
2855
+ {
2856
+ doenetML: `
2857
+ <text>a</text>
2858
+ <graph>
2859
+ <function minima="(3,4)" through="(-1,5) (4,2)" maxima="(1,0)" />
2860
+ <derivative stylenumber="2"><copy target="_function1"/></derivative>
2861
+ <derivative stylenumber="3"><copy target="_derivative1"/></derivative>
2862
+ <derivative stylenumber="4"><copy target="_derivative2"/></derivative>
2863
+ <derivative stylenumber="5"><copy target="_derivative3"/></derivative>
2864
+ </graph>
2865
+ `,
2866
+ },
2867
+ "*",
2868
+ );
2869
+ });
2870
+
2871
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
2872
+
2873
+ cy.window().then(async (win) => {
2874
+ let stateVariables = await win.returnAllStateVariables1();
2875
+
2876
+ let dx = 0.0001;
2877
+
2878
+ let f = createFunctionFromDefinition(
2879
+ stateVariables["/_function1"].stateValues.fDefinitions[0],
2880
+ );
2881
+ let d1 = createFunctionFromDefinition(
2882
+ stateVariables["/_derivative1"].stateValues.fDefinitions[0],
2883
+ );
2884
+ let d2 = createFunctionFromDefinition(
2885
+ stateVariables["/_derivative2"].stateValues.fDefinitions[0],
2886
+ );
2887
+ let d3 = createFunctionFromDefinition(
2888
+ stateVariables["/_derivative3"].stateValues.fDefinitions[0],
2889
+ );
2890
+ let d4 = createFunctionFromDefinition(
2891
+ stateVariables["/_derivative4"].stateValues.fDefinitions[0],
2892
+ );
2893
+
2894
+ // make sure we don't get within dx of a grid point
2895
+ for (let x = -10.02412412; x <= 10; x += 0.5) {
2896
+ let f0 = f(x);
2897
+ let f1 = f(x + dx);
2898
+ let fp05 = d1(x + dx / 2);
2899
+ expect(fp05).closeTo((f1 - f0) / dx, 1e-6);
2900
+
2901
+ let fpn05 = d1(x - dx / 2);
2902
+ let fpp0 = d2(x);
2903
+ expect(fpp0).closeTo((fp05 - fpn05) / dx, 1e-6);
2904
+
2905
+ let fpp1 = d2(x + dx);
2906
+ let fppp05 = d3(x + dx / 2);
2907
+ expect(fppp05).closeTo((fpp1 - fpp0) / dx, 1e-6);
2908
+
2909
+ let fpppn05 = d3(x - dx / 2);
2910
+ let fpppp0 = d4(x);
2911
+ expect(fpppp0).closeTo((fppp05 - fpppn05) / dx, 1e-6);
2912
+ }
2913
+ });
2914
+ });
2915
+
2916
+ it("derivatives of interpolated function specified with variables", () => {
2917
+ cy.window().then(async (win) => {
2918
+ win.postMessage(
2919
+ {
2920
+ doenetML: `
2921
+ <text>a</text>
2922
+ <function name="f" variables="x" maxima="(5,-3)" minima="(-5,3)" />
2923
+ <function name="g" styleNumber="2" variable="y" minima="(3,-9)" maxima="(-3,9)" />
2924
+
2925
+ <derivative name="df1">$f</derivative>
2926
+ <derivative name="dg1" styleNumber="2">$g</derivative>
2927
+
2928
+ <derivative name="df1b" derivVariables="x">$f</derivative>
2929
+ <derivative name="zero1" derivVariable="x" styleNumber="2">$g</derivative>
2930
+
2931
+ <derivative name="zero2" derivVariables="y">$f</derivative>
2932
+ <derivative name="dg1b" derivVariable="y" styleNumber="2">$g</derivative>
2933
+
2934
+ <derivative name="df2" derivVariables="x x">$f</derivative>
2935
+ <derivative name="dg2" derivVariables="y y" styleNumber="2">$g</derivative>
2936
+
2937
+ <derivative name="zero3" derivVariables="x y">$f</derivative>
2938
+ <derivative name="zero4" derivVariables="x y" styleNumber="2">$g</derivative>
2939
+
2940
+ <derivative name="zero5" derivVariables="y x">$f</derivative>
2941
+ <derivative name="zero6" derivVariables="y x" styleNumber="2">$g</derivative>
2942
+
2943
+ <derivative name="df3" derivVariables="x x x">$f</derivative>
2944
+ <derivative name="dg3" derivVariables="y y y" styleNumber="2">$g</derivative>
2945
+
2946
+ <derivative name="df4" derivVariables="x x x x">$f</derivative>
2947
+ <derivative name="dg4" derivVariables="y y y y" styleNumber="2">$g</derivative>
2948
+
2949
+ `,
2950
+ },
2951
+ "*",
2952
+ );
2953
+ });
2954
+
2955
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
2956
+
2957
+ cy.window().then(async (win) => {
2958
+ let stateVariables = await win.returnAllStateVariables1();
2959
+
2960
+ let dx = 0.0001;
2961
+
2962
+ let f = createFunctionFromDefinition(
2963
+ stateVariables["/f"].stateValues.fDefinitions[0],
2964
+ );
2965
+ let df1 = createFunctionFromDefinition(
2966
+ stateVariables["/df1"].stateValues.fDefinitions[0],
2967
+ );
2968
+ let df1b = createFunctionFromDefinition(
2969
+ stateVariables["/df1b"].stateValues.fDefinitions[0],
2970
+ );
2971
+ let df2 = createFunctionFromDefinition(
2972
+ stateVariables["/df2"].stateValues.fDefinitions[0],
2973
+ );
2974
+ let df3 = createFunctionFromDefinition(
2975
+ stateVariables["/df3"].stateValues.fDefinitions[0],
2976
+ );
2977
+ let df4 = createFunctionFromDefinition(
2978
+ stateVariables["/df4"].stateValues.fDefinitions[0],
2979
+ );
2980
+ let g = createFunctionFromDefinition(
2981
+ stateVariables["/g"].stateValues.fDefinitions[0],
2982
+ );
2983
+ let dg1 = createFunctionFromDefinition(
2984
+ stateVariables["/dg1"].stateValues.fDefinitions[0],
2985
+ );
2986
+ let dg1b = createFunctionFromDefinition(
2987
+ stateVariables["/dg1b"].stateValues.fDefinitions[0],
2988
+ );
2989
+ let dg2 = createFunctionFromDefinition(
2990
+ stateVariables["/dg2"].stateValues.fDefinitions[0],
2991
+ );
2992
+ let dg3 = createFunctionFromDefinition(
2993
+ stateVariables["/dg3"].stateValues.fDefinitions[0],
2994
+ );
2995
+ let dg4 = createFunctionFromDefinition(
2996
+ stateVariables["/dg4"].stateValues.fDefinitions[0],
2997
+ );
2998
+ let zero1 = createFunctionFromDefinition(
2999
+ stateVariables["/zero1"].stateValues.fDefinitions[0],
3000
+ );
3001
+ let zero2 = createFunctionFromDefinition(
3002
+ stateVariables["/zero2"].stateValues.fDefinitions[0],
3003
+ );
3004
+ let zero3 = createFunctionFromDefinition(
3005
+ stateVariables["/zero3"].stateValues.fDefinitions[0],
3006
+ );
3007
+ let zero4 = createFunctionFromDefinition(
3008
+ stateVariables["/zero4"].stateValues.fDefinitions[0],
3009
+ );
3010
+ let zero5 = createFunctionFromDefinition(
3011
+ stateVariables["/zero5"].stateValues.fDefinitions[0],
3012
+ );
3013
+ let zero6 = createFunctionFromDefinition(
3014
+ stateVariables["/zero6"].stateValues.fDefinitions[0],
3015
+ );
3016
+
3017
+ // make sure we don't get within dx of a grid point
3018
+ for (let x = -10.02412412; x <= 10; x += 0.5) {
3019
+ let f_0 = f(x);
3020
+ let f_1 = f(x + dx);
3021
+ let df1_05 = df1(x + dx / 2);
3022
+ let df1b_05 = df1b(x + dx / 2);
3023
+ expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6);
3024
+ expect(df1b_05).eq(df1_05);
3025
+
3026
+ let g_0 = g(x);
3027
+ let g_1 = g(x + dx);
3028
+ let dg1_05 = dg1(x + dx / 2);
3029
+ let dg1b_05 = dg1b(x + dx / 2);
3030
+ expect(dg1_05).closeTo((g_1 - g_0) / dx, 1e-6);
3031
+ expect(dg1b_05).eq(dg1_05);
3032
+
3033
+ let df1_n05 = df1(x - dx / 2);
3034
+ let df2_0 = df2(x);
3035
+ expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6);
3036
+
3037
+ let dg1_n05 = dg1(x - dx / 2);
3038
+ let dg2_0 = dg2(x);
3039
+ expect(dg2_0).closeTo((dg1b_05 - dg1_n05) / dx, 1e-6);
3040
+
3041
+ let df2_1 = df2(x + dx);
3042
+ let df3_05 = df3(x + dx / 2);
3043
+ expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6);
3044
+
3045
+ let dg2_1 = dg2(x + dx);
3046
+ let dg3_05 = dg3(x + dx / 2);
3047
+ expect(dg3_05).closeTo((dg2_1 - dg2_0) / dx, 1e-6);
3048
+
3049
+ let df3_n05 = df3(x - dx / 2);
3050
+ let df4_0 = df4(x);
3051
+ expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6);
3052
+
3053
+ let dg3_n05 = dg3(x - dx / 2);
3054
+ let dg4_0 = dg4(x);
3055
+ expect(dg4_0).closeTo((dg3_05 - dg3_n05) / dx, 1e-6);
3056
+
3057
+ expect(zero1(x)).eq(0);
3058
+ expect(zero2(x)).eq(0);
3059
+ expect(zero3(x)).eq(0);
3060
+ expect(zero4(x)).eq(0);
3061
+ expect(zero5(x)).eq(0);
3062
+ expect(zero6(x)).eq(0);
3063
+ }
3064
+ });
3065
+ });
3066
+
3067
+ it("derivatives of interpolated function with changed variables", () => {
3068
+ cy.window().then(async (win) => {
3069
+ win.postMessage(
3070
+ {
3071
+ doenetML: `
3072
+ <text>a</text>
3073
+ <function name="f" variables="x" maxima="(5,-3)" minima="(-5,3)" />
3074
+ <function name="g" styleNumber="2" variable="y" >$f</function>
3075
+ <function name="h" styleNumber="3" variables="z" >$g</function>
3076
+
3077
+ <derivative name="df1">$f</derivative>
3078
+ <derivative name="dg1" styleNumber="2">$g</derivative>
3079
+ <derivative name="dh1" styleNumber="3">$h</derivative>
3080
+
3081
+ <derivative name="df1b" derivVariable="x">$f</derivative>
3082
+ <derivative name="zero1" derivVariables="x" styleNumber="2">$g</derivative>
3083
+ <derivative name="zero2" derivVariable="x" styleNumber="3">$h</derivative>
3084
+
3085
+ <derivative name="zero3" derivVariables="y">$f</derivative>
3086
+ <derivative name="dg1b" derivVariable="y" styleNumber="2">$g</derivative>
3087
+ <derivative name="zero4" derivVariables="y" styleNumber="3">$h</derivative>
3088
+
3089
+ <derivative name="zero5" derivVariable="z">$f</derivative>
3090
+ <derivative name="zero6" derivVariables="z" styleNumber="2">$g</derivative>
3091
+ <derivative name="dh1b" derivVariable="z" styleNumber="3">$h</derivative>
3092
+
3093
+ <derivative name="df2" derivVariables="x x">$f</derivative>
3094
+ <derivative name="dg2" derivVariables="y y" styleNumber="2">$g</derivative>
3095
+ <derivative name="dh2" derivVariables="z z" styleNumber="3">$h</derivative>
3096
+
3097
+ <derivative name="df2b" derivVariable="x"><derivative derivVariable="x">$f</derivative></derivative>
3098
+ <derivative name="dg2b" derivVariables="y" styleNumber="2"><derivative derivVariables="y">$g</derivative></derivative>
3099
+ <derivative name="dh2b" derivVariables="z" styleNumber="3"><derivative derivVariable="z">$h</derivative></derivative>
3100
+
3101
+ <derivative name="zero7" derivVariables="x y">$f</derivative>
3102
+ <derivative name="zero8" derivVariables="x y" styleNumber="2">$g</derivative>
3103
+ <derivative name="zero9" derivVariables="x y" styleNumber="3">$h</derivative>
3104
+
3105
+ <derivative name="zero10" derivVariables="y x">$f</derivative>
3106
+ <derivative name="zero11" derivVariables="y x" styleNumber="2">$g</derivative>
3107
+ <derivative name="zero12" derivVariables="y x" styleNumber="3">$h</derivative>
3108
+
3109
+ <derivative name="df3" derivVariables="x x x">$f</derivative>
3110
+ <derivative name="dg3" derivVariables="y y y" styleNumber="2">$g</derivative>
3111
+ <derivative name="dh3" derivVariables="z z z" styleNumber="2">$h</derivative>
3112
+
3113
+ <derivative name="df4" derivVariables="x x x x">$f</derivative>
3114
+ <derivative name="dg4" derivVariables="y y y y" styleNumber="2">$g</derivative>
3115
+ <derivative name="dh4" derivVariables="z z z z" styleNumber="2">$h</derivative>
3116
+
3117
+ <number name="dx">0.0001</number>
3118
+ <map assignNames="
3119
+ t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t14 t15 t16 t17 t18 t19 t20
3120
+ t21 t22 t23 t24 t25 t26 t27 t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41
3121
+ ">
3122
+ <template newNamespace>
3123
+ <p><aslist>
3124
+ <evaluate function="$(../f)" input="$x" name="f_0" />
3125
+ <evaluate function="$(../df1)" input="$x+$(../dx)/2" name="df1_05" />
3126
+ <evaluate function="$(../df1b)" input="$x+$(../dx)/2" name="df1b_05" />
3127
+ <evaluate function="$(../df2)" input="$x" name="df2_0" />
3128
+ <evaluate function="$(../df2b)" input="$x" name="df2b_0" />
3129
+ <evaluate function="$(../df3)" input="$x+$(../dx)/2" name="df3_05" />
3130
+ <evaluate function="$(../df4)" input="$x" name="df4_0" />
3131
+
3132
+ <evaluate function="$(../g)" input="$x" name="g_0" />
3133
+ <evaluate function="$(../dg1)" input="$x+$(../dx)/2" name="dg1_05" />
3134
+ <evaluate function="$(../dg1b)" input="$x+$(../dx)/2" name="dg1b_05" />
3135
+ <evaluate function="$(../dg2)" input="$x" name="dg2_0" />
3136
+ <evaluate function="$(../dg2b)" input="$x" name="dg2b_0" />
3137
+ <evaluate function="$(../dg3)" input="$x+$(../dx)/2" name="dg3_05" />
3138
+ <evaluate function="$(../dg4)" input="$x" name="dg4_0" />
3139
+
3140
+ <evaluate function="$(../h)" input="$x" name="h_0" />
3141
+ <evaluate function="$(../dh1)" input="$x+$(../dx)/2" name="dh1_05" />
3142
+ <evaluate function="$(../dh1b)" input="$x+$(../dx)/2" name="dh1b_05" />
3143
+ <evaluate function="$(../dh2)" input="$x" name="dh2_0" />
3144
+ <evaluate function="$(../dh2b)" input="$x" name="dh2b_0" />
3145
+ <evaluate function="$(../dh3)" input="$x+$(../dx)/2" name="dh3_05" />
3146
+ <evaluate function="$(../dh4)" input="$x" name="dh4_0" />
3147
+ </aslist></p>
3148
+ </template>
3149
+ <sources alias="x">
3150
+ <sequence from="-10.02412412" to="10" step="3.1" />
3151
+ </sources>
3152
+ </map>
3153
+
3154
+ `,
3155
+ },
3156
+ "*",
3157
+ );
3158
+ });
3159
+
3160
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
3161
+
3162
+ cy.window().then(async (win) => {
3163
+ let stateVariables = await win.returnAllStateVariables1();
3164
+
3165
+ let dx = 0.0001;
3166
+
3167
+ let f = createFunctionFromDefinition(
3168
+ stateVariables["/f"].stateValues.fDefinitions[0],
3169
+ );
3170
+ let df1 = createFunctionFromDefinition(
3171
+ stateVariables["/df1"].stateValues.fDefinitions[0],
3172
+ );
3173
+ let df1b = createFunctionFromDefinition(
3174
+ stateVariables["/df1b"].stateValues.fDefinitions[0],
3175
+ );
3176
+ let df2 = createFunctionFromDefinition(
3177
+ stateVariables["/df2"].stateValues.fDefinitions[0],
3178
+ );
3179
+ let df2b = createFunctionFromDefinition(
3180
+ stateVariables["/df2b"].stateValues.fDefinitions[0],
3181
+ );
3182
+ let df3 = createFunctionFromDefinition(
3183
+ stateVariables["/df3"].stateValues.fDefinitions[0],
3184
+ );
3185
+ let df4 = createFunctionFromDefinition(
3186
+ stateVariables["/df4"].stateValues.fDefinitions[0],
3187
+ );
3188
+ let g = createFunctionFromDefinition(
3189
+ stateVariables["/g"].stateValues.fDefinitions[0],
3190
+ );
3191
+ let dg1 = createFunctionFromDefinition(
3192
+ stateVariables["/dg1"].stateValues.fDefinitions[0],
3193
+ );
3194
+ let dg1b = createFunctionFromDefinition(
3195
+ stateVariables["/dg1b"].stateValues.fDefinitions[0],
3196
+ );
3197
+ let dg2 = createFunctionFromDefinition(
3198
+ stateVariables["/dg2"].stateValues.fDefinitions[0],
3199
+ );
3200
+ let dg2b = createFunctionFromDefinition(
3201
+ stateVariables["/dg2b"].stateValues.fDefinitions[0],
3202
+ );
3203
+ let dg3 = createFunctionFromDefinition(
3204
+ stateVariables["/dg3"].stateValues.fDefinitions[0],
3205
+ );
3206
+ let dg4 = createFunctionFromDefinition(
3207
+ stateVariables["/dg4"].stateValues.fDefinitions[0],
3208
+ );
3209
+ let h = createFunctionFromDefinition(
3210
+ stateVariables["/h"].stateValues.fDefinitions[0],
3211
+ );
3212
+ let dh1 = createFunctionFromDefinition(
3213
+ stateVariables["/dh1"].stateValues.fDefinitions[0],
3214
+ );
3215
+ let dh1b = createFunctionFromDefinition(
3216
+ stateVariables["/dh1b"].stateValues.fDefinitions[0],
3217
+ );
3218
+ let dh2 = createFunctionFromDefinition(
3219
+ stateVariables["/dh2"].stateValues.fDefinitions[0],
3220
+ );
3221
+ let dh2b = createFunctionFromDefinition(
3222
+ stateVariables["/dh2b"].stateValues.fDefinitions[0],
3223
+ );
3224
+ let dh3 = createFunctionFromDefinition(
3225
+ stateVariables["/dh3"].stateValues.fDefinitions[0],
3226
+ );
3227
+ let dh4 = createFunctionFromDefinition(
3228
+ stateVariables["/dh4"].stateValues.fDefinitions[0],
3229
+ );
3230
+ let zero1 = createFunctionFromDefinition(
3231
+ stateVariables["/zero1"].stateValues.fDefinitions[0],
3232
+ );
3233
+ let zero2 = createFunctionFromDefinition(
3234
+ stateVariables["/zero2"].stateValues.fDefinitions[0],
3235
+ );
3236
+ let zero3 = createFunctionFromDefinition(
3237
+ stateVariables["/zero3"].stateValues.fDefinitions[0],
3238
+ );
3239
+ let zero4 = createFunctionFromDefinition(
3240
+ stateVariables["/zero4"].stateValues.fDefinitions[0],
3241
+ );
3242
+ let zero5 = createFunctionFromDefinition(
3243
+ stateVariables["/zero5"].stateValues.fDefinitions[0],
3244
+ );
3245
+ let zero6 = createFunctionFromDefinition(
3246
+ stateVariables["/zero6"].stateValues.fDefinitions[0],
3247
+ );
3248
+ let zero7 = createFunctionFromDefinition(
3249
+ stateVariables["/zero7"].stateValues.fDefinitions[0],
3250
+ );
3251
+ let zero8 = createFunctionFromDefinition(
3252
+ stateVariables["/zero8"].stateValues.fDefinitions[0],
3253
+ );
3254
+ let zero9 = createFunctionFromDefinition(
3255
+ stateVariables["/zero9"].stateValues.fDefinitions[0],
3256
+ );
3257
+ let zero10 = createFunctionFromDefinition(
3258
+ stateVariables["/zero10"].stateValues.fDefinitions[0],
3259
+ );
3260
+ let zero11 = createFunctionFromDefinition(
3261
+ stateVariables["/zero11"].stateValues.fDefinitions[0],
3262
+ );
3263
+ let zero12 = createFunctionFromDefinition(
3264
+ stateVariables["/zero12"].stateValues.fDefinitions[0],
3265
+ );
3266
+
3267
+ let i = 0;
3268
+
3269
+ // make sure we don't get within dx of a grid point
3270
+ for (let x = -10.02412412; x <= 10; x += 3.1) {
3271
+ i++;
3272
+
3273
+ let f_0 = f(x);
3274
+ let f_1 = f(x + dx);
3275
+ let df1_05 = df1(x + dx / 2);
3276
+ let df1b_05 = df1b(x + dx / 2);
3277
+ expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6);
3278
+ expect(df1b_05).eq(df1_05);
3279
+
3280
+ let f_0a = stateVariables[`/t${i}/f_0`].stateValues.value;
3281
+ expect(f_0a).closeTo(f_0, 1e-10);
3282
+ let df1_05a = stateVariables[`/t${i}/df1_05`].stateValues.value;
3283
+ expect(df1_05a).closeTo(df1_05, 1e-10);
3284
+ let df1b_05a = stateVariables[`/t${i}/df1b_05`].stateValues.value;
3285
+ expect(df1b_05a).closeTo(df1b_05, 1e-10);
3286
+
3287
+ let g_0 = g(x);
3288
+ let g_1 = g(x + dx);
3289
+ expect(g_0).eq(f_0);
3290
+ expect(g_1).eq(f_1);
3291
+ let dg1_05 = dg1(x + dx / 2);
3292
+ let dg1b_05 = dg1b(x + dx / 2);
3293
+ expect(dg1_05).closeTo((g_1 - g_0) / dx, 1e-6);
3294
+ expect(dg1b_05).eq(dg1_05);
3295
+
3296
+ let g_0a = stateVariables[`/t${i}/g_0`].stateValues.value;
3297
+ expect(g_0a).closeTo(f_0, 1e-10);
3298
+ let dg1_05a = stateVariables[`/t${i}/dg1_05`].stateValues.value;
3299
+ expect(dg1_05a).closeTo(df1_05, 1e-10);
3300
+ let dg1b_05a = stateVariables[`/t${i}/dg1b_05`].stateValues.value;
3301
+ expect(dg1b_05a).closeTo(df1b_05, 1e-10);
3302
+
3303
+ let h_0 = h(x);
3304
+ let h_1 = h(x + dx);
3305
+ expect(h_0).eq(f_0);
3306
+ expect(h_1).eq(f_1);
3307
+ let dh1_05 = dh1(x + dx / 2);
3308
+ let dh1b_05 = dh1b(x + dx / 2);
3309
+ expect(dh1_05).closeTo((h_1 - h_0) / dx, 1e-6);
3310
+ expect(dh1b_05).eq(dh1_05);
3311
+
3312
+ let h_0a = stateVariables[`/t${i}/h_0`].stateValues.value;
3313
+ expect(h_0a).closeTo(f_0, 1e-10);
3314
+ let dh1_05a = stateVariables[`/t${i}/dh1_05`].stateValues.value;
3315
+ expect(dh1_05a).closeTo(df1_05, 1e-10);
3316
+ let dh1b_05a = stateVariables[`/t${i}/dh1b_05`].stateValues.value;
3317
+ expect(dh1b_05a).closeTo(df1b_05, 1e-10);
3318
+
3319
+ let df1_n05 = df1(x - dx / 2);
3320
+ let df2_0 = df2(x);
3321
+ expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6);
3322
+
3323
+ let df2_0a = stateVariables[`/t${i}/df2_0`].stateValues.value;
3324
+ expect(df2_0a).closeTo(df2_0, 1e-10);
3325
+
3326
+ let dg2_0 = dg2(x);
3327
+ expect(dg2_0).eq(df2_0);
3328
+
3329
+ let dg2_0a = stateVariables[`/t${i}/dg2_0`].stateValues.value;
3330
+ expect(dg2_0a).closeTo(df2_0, 1e-10);
3331
+
3332
+ let dh2_0 = dh2(x);
3333
+ expect(dh2_0).eq(df2_0);
3334
+
3335
+ let dh2_0a = stateVariables[`/t${i}/dh2_0`].stateValues.value;
3336
+ expect(dh2_0a).closeTo(df2_0, 1e-10);
3337
+
3338
+ let df2b_0 = df2b(x);
3339
+ expect(df2b_0).eq(df2_0);
3340
+
3341
+ let df2b_0a = stateVariables[`/t${i}/df2b_0`].stateValues.value;
3342
+ expect(df2b_0a).closeTo(df2b_0, 1e-10);
3343
+
3344
+ let dg2b_0 = dg2b(x);
3345
+ expect(dg2b_0).eq(dg2_0);
3346
+
3347
+ let dg2b_0a = stateVariables[`/t${i}/dg2b_0`].stateValues.value;
3348
+ expect(dg2b_0a).closeTo(df2b_0, 1e-10);
3349
+
3350
+ let dh2b_0 = dh2b(x);
3351
+ expect(dh2b_0).eq(dh2_0);
3352
+
3353
+ let dh2b_0a = stateVariables[`/t${i}/dh2b_0`].stateValues.value;
3354
+ expect(dh2b_0a).closeTo(df2b_0, 1e-10);
3355
+
3356
+ let df2_1 = df2(x + dx);
3357
+ let df3_05 = df3(x + dx / 2);
3358
+ expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6);
3359
+
3360
+ let df3_05a = stateVariables[`/t${i}/df3_05`].stateValues.value;
3361
+ expect(df3_05a).closeTo(df3_05, 1e-10);
3362
+
3363
+ let dg3_05 = dg3(x + dx / 2);
3364
+ expect(dg3_05).eq(df3_05);
3365
+
3366
+ let dg3_05a = stateVariables[`/t${i}/dg3_05`].stateValues.value;
3367
+ expect(dg3_05a).closeTo(df3_05, 1e-10);
3368
+
3369
+ let dh3_05 = dh3(x + dx / 2);
3370
+ expect(dh3_05).eq(df3_05);
3371
+
3372
+ let dh3_05a = stateVariables[`/t${i}/dh3_05`].stateValues.value;
3373
+ expect(dh3_05a).closeTo(df3_05, 1e-10);
3374
+
3375
+ let df3_n05 = df3(x - dx / 2);
3376
+ let df4_0 = df4(x);
3377
+ expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6);
3378
+
3379
+ let df4_0a = stateVariables[`/t${i}/df4_0`].stateValues.value;
3380
+ expect(df4_0a).closeTo(df4_0, 1e-10);
3381
+
3382
+ let dg4_0 = dg4(x);
3383
+ expect(dg4_0).eq(df4_0);
3384
+
3385
+ let dg4_0a = stateVariables[`/t${i}/dg4_0`].stateValues.value;
3386
+ expect(dg4_0a).closeTo(df4_0, 1e-10);
3387
+
3388
+ let dh4_0 = dh4(x);
3389
+ expect(dh4_0).eq(df4_0);
3390
+
3391
+ let dh4_0a = stateVariables[`/t${i}/dh4_0`].stateValues.value;
3392
+ expect(dh4_0a).closeTo(df4_0, 1e-10);
3393
+
3394
+ expect(zero1(x)).eq(0);
3395
+ expect(zero2(x)).eq(0);
3396
+ expect(zero3(x)).eq(0);
3397
+ expect(zero4(x)).eq(0);
3398
+ expect(zero5(x)).eq(0);
3399
+ expect(zero6(x)).eq(0);
3400
+ expect(zero7(x)).eq(0);
3401
+ expect(zero8(x)).eq(0);
3402
+ expect(zero9(x)).eq(0);
3403
+ expect(zero10(x)).eq(0);
3404
+ expect(zero11(x)).eq(0);
3405
+ expect(zero12(x)).eq(0);
3406
+ }
3407
+ });
3408
+ });
3409
+
3410
+ it("derivatives of interpolated function with changed variables, subscript", () => {
3411
+ cy.window().then(async (win) => {
3412
+ win.postMessage(
3413
+ {
3414
+ doenetML: `
3415
+ <text>a</text>
3416
+ <function name="f" variable="x_1" maxima="(5,-3)" minima="(-5,3)" />
3417
+ <function name="g" styleNumber="2" variables="x_2" >$f</function>
3418
+
3419
+ <derivative name="df1">$f</derivative>
3420
+ <derivative name="dg1" styleNumber="2">$g</derivative>
3421
+
3422
+ <derivative name="df1b" derivVariable="x_1">$f</derivative>
3423
+ <derivative name="zero1" derivVariables="x_1" styleNumber="2">$g</derivative>
3424
+
3425
+ <derivative name="zero2" derivVariables="x_2">$f</derivative>
3426
+ <derivative name="dg1b" derivVariable="x_2" styleNumber="2">$g</derivative>
3427
+
3428
+ <derivative name="df2" derivVariables="x_1 x_1">$f</derivative>
3429
+ <derivative name="dg2" derivVariables="x_2 x_2" styleNumber="2">$g</derivative>
3430
+
3431
+ <derivative name="df2b" derivVariable="x_1"><derivative derivVariable="x_1">$f</derivative></derivative>
3432
+ <derivative name="dg2b" derivVariables="x_2" styleNumber="2"><derivative derivVariables="x_2">$g</derivative></derivative>
3433
+
3434
+ <derivative name="zero3" derivVariables="x_1 x_2">$f</derivative>
3435
+ <derivative name="zero4" derivVariables="x_1 x_2" styleNumber="2">$g</derivative>
3436
+
3437
+ <derivative name="zero5" derivVariables="x_2 x_1">$f</derivative>
3438
+ <derivative name="zero6" derivVariables="x_2 x_1" styleNumber="2">$g</derivative>
3439
+
3440
+ <derivative name="df3" derivVariables="x_1 x_1 x_1">$f</derivative>
3441
+ <derivative name="dg3" derivVariables="x_2 x_2 x_2" styleNumber="2">$g</derivative>
3442
+
3443
+ <derivative name="df4" derivVariables="x_1 x_1 x_1 x_1">$f</derivative>
3444
+ <derivative name="dg4" derivVariables="x_2 x_2 x_2 x_2" styleNumber="2">$g</derivative>
3445
+
3446
+ `,
3447
+ },
3448
+ "*",
3449
+ );
3450
+ });
3451
+
3452
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
3453
+
3454
+ cy.window().then(async (win) => {
3455
+ let stateVariables = await win.returnAllStateVariables1();
3456
+
3457
+ let dx = 0.0001;
3458
+
3459
+ let f = createFunctionFromDefinition(
3460
+ stateVariables["/f"].stateValues.fDefinitions[0],
3461
+ );
3462
+ let df1 = createFunctionFromDefinition(
3463
+ stateVariables["/df1"].stateValues.fDefinitions[0],
3464
+ );
3465
+ let df1b = createFunctionFromDefinition(
3466
+ stateVariables["/df1b"].stateValues.fDefinitions[0],
3467
+ );
3468
+ let df2 = createFunctionFromDefinition(
3469
+ stateVariables["/df2"].stateValues.fDefinitions[0],
3470
+ );
3471
+ let df2b = createFunctionFromDefinition(
3472
+ stateVariables["/df2b"].stateValues.fDefinitions[0],
3473
+ );
3474
+ let df3 = createFunctionFromDefinition(
3475
+ stateVariables["/df3"].stateValues.fDefinitions[0],
3476
+ );
3477
+ let df4 = createFunctionFromDefinition(
3478
+ stateVariables["/df4"].stateValues.fDefinitions[0],
3479
+ );
3480
+ let g = createFunctionFromDefinition(
3481
+ stateVariables["/g"].stateValues.fDefinitions[0],
3482
+ );
3483
+ let dg1 = createFunctionFromDefinition(
3484
+ stateVariables["/dg1"].stateValues.fDefinitions[0],
3485
+ );
3486
+ let dg1b = createFunctionFromDefinition(
3487
+ stateVariables["/dg1b"].stateValues.fDefinitions[0],
3488
+ );
3489
+ let dg2 = createFunctionFromDefinition(
3490
+ stateVariables["/dg2"].stateValues.fDefinitions[0],
3491
+ );
3492
+ let dg2b = createFunctionFromDefinition(
3493
+ stateVariables["/dg2b"].stateValues.fDefinitions[0],
3494
+ );
3495
+ let dg3 = createFunctionFromDefinition(
3496
+ stateVariables["/dg3"].stateValues.fDefinitions[0],
3497
+ );
3498
+ let dg4 = createFunctionFromDefinition(
3499
+ stateVariables["/dg4"].stateValues.fDefinitions[0],
3500
+ );
3501
+ let zero1 = createFunctionFromDefinition(
3502
+ stateVariables["/zero1"].stateValues.fDefinitions[0],
3503
+ );
3504
+ let zero2 = createFunctionFromDefinition(
3505
+ stateVariables["/zero2"].stateValues.fDefinitions[0],
3506
+ );
3507
+ let zero3 = createFunctionFromDefinition(
3508
+ stateVariables["/zero3"].stateValues.fDefinitions[0],
3509
+ );
3510
+ let zero4 = createFunctionFromDefinition(
3511
+ stateVariables["/zero4"].stateValues.fDefinitions[0],
3512
+ );
3513
+ let zero5 = createFunctionFromDefinition(
3514
+ stateVariables["/zero5"].stateValues.fDefinitions[0],
3515
+ );
3516
+ let zero6 = createFunctionFromDefinition(
3517
+ stateVariables["/zero6"].stateValues.fDefinitions[0],
3518
+ );
3519
+
3520
+ // make sure we don't get within dx of a grid point
3521
+ for (let x = -10.02412412; x <= 10; x += 0.5) {
3522
+ let f_0 = f(x);
3523
+ let f_1 = f(x + dx);
3524
+ let df1_05 = df1(x + dx / 2);
3525
+ let df1b_05 = df1b(x + dx / 2);
3526
+ expect(df1_05).closeTo((f_1 - f_0) / dx, 1e-6);
3527
+ expect(df1b_05).eq(df1_05);
3528
+
3529
+ let dg1_05 = dg1(x + dx / 2);
3530
+ let dg1b_05 = dg1b(x + dx / 2);
3531
+ expect(dg1_05).eq(dg1_05);
3532
+ expect(dg1b_05).eq(dg1_05);
3533
+
3534
+ let df1_n05 = df1(x - dx / 2);
3535
+ let df2_0 = df2(x);
3536
+ expect(df2_0).closeTo((df1b_05 - df1_n05) / dx, 1e-6);
3537
+
3538
+ let dg2_0 = dg2(x);
3539
+ expect(dg2_0).eq(df2_0);
3540
+
3541
+ let df2b_0 = df2b(x);
3542
+ expect(df2b_0).eq(df2_0);
3543
+
3544
+ let dg2b_0 = dg2b(x);
3545
+ expect(dg2b_0).eq(dg2_0);
3546
+
3547
+ let df2_1 = df2(x + dx);
3548
+ let df3_05 = df3(x + dx / 2);
3549
+ expect(df3_05).closeTo((df2_1 - df2_0) / dx, 1e-6);
3550
+
3551
+ let dg3_05 = dg3(x + dx / 2);
3552
+ expect(dg3_05).eq(df3_05);
3553
+
3554
+ let df3_n05 = df3(x - dx / 2);
3555
+ let df4_0 = df4(x);
3556
+ expect(df4_0).closeTo((df3_05 - df3_n05) / dx, 1e-6);
3557
+
3558
+ let dg4_0 = dg4(x);
3559
+ expect(dg4_0).eq(df4_0);
3560
+
3561
+ expect(zero1(x)).eq(0);
3562
+ expect(zero2(x)).eq(0);
3563
+ expect(zero3(x)).eq(0);
3564
+ expect(zero4(x)).eq(0);
3565
+ expect(zero5(x)).eq(0);
3566
+ expect(zero6(x)).eq(0);
3567
+ }
3568
+ });
3569
+ });
3570
+
3571
+ it("extrema of derivative", () => {
3572
+ cy.window().then(async (win) => {
3573
+ win.postMessage(
3574
+ {
3575
+ doenetML: `
3576
+ <text>a</text>
3577
+ <p><m>c_1 =</m> <mathinput name="c_1" prefill="1" /></p>
3578
+ <p><m>c_2 =</m> <mathinput name="c_2" prefill="1" /></p>
3579
+ <p><m>c_3 =</m> <mathinput name="c_3" prefill="3" /></p>
3580
+ <p><m>c_4 =</m> <mathinput name="c_4" prefill="4" /></p>
3581
+ <p><m>c_5 =</m> <mathinput name="c_5" prefill="5" /></p>
3582
+ <p><m>c_6 =</m> <mathinput name="c_6" prefill="1" /></p>
3583
+ <p><m>x =</m> <mathinput name="x" prefill="x" /></p>
3584
+
3585
+ <math hide name="formula" simplify>
3586
+ $c_1 $x^5/20 - $c_1($c_2+$c_3+$c_4) $x^4/12
3587
+ + $c_1($c_2*$c_3 + $c_2 $c_4 + $c_3$c_4)$x^3/6
3588
+ - $c_1$c_2$c_3$c_4$x^2/2 + $c_5$x + $c_6
3589
+ </math>
3590
+
3591
+ <p><m>f($x) =
3592
+ <function name="f" variable="$x">$formula</function>
3593
+ </m></p>
3594
+
3595
+ <p><m>f'($x) =
3596
+ <derivative name="fp">$f</derivative>
3597
+ </m></p>
3598
+
3599
+ <p>again, <m>f'($x) = <copy target="fp" name="fp2" />
3600
+ </m></p>
3601
+
3602
+
3603
+ <p>Number of minima of f': <copy prop="numMinima" assignNames="nMinima" target="fp" /></p>
3604
+ <p>Minima of f': <extract prop="coords" displayDecimals="5" assignNames="min1 min2"><copy prop="minima" target="fp" /></extract></p>
3605
+
3606
+ <p>Number of maxima of f': <copy prop="numMaxima" assignNames="nMaxima" target="fp" /></p>
3607
+ <p>Maxima of f': <extract prop="coords" displayDecimals="5" assignNames="max1 max2"><copy prop="maxima" target="fp" /></extract></p>
3608
+
3609
+ <p>To repeat:</p>
3610
+ <p>Number of minima of f': <copy prop="numMinima" assignNames="nMinima2" target="fp2" /></p>
3611
+ <p>Minima of f': <extract prop="coords" displayDecimals="5" assignNames="min12 min22"><copy prop="minima" target="fp2" /></extract></p>
3612
+
3613
+ <p>Number of maxima of f': <copy prop="numMaxima" assignNames="nMaxima2" target="fp2" /></p>
3614
+ <p>Maxima of f': <extract prop="coords" displayDecimals="5" assignNames="max12 max22"><copy prop="maxima" target="fp2" /></extract></p>
3615
+
3616
+
3617
+ <p>
3618
+ <copy prop="value" target="c_1" assignNames="c_1a" />
3619
+ <copy prop="value" target="c_2" assignNames="c_2a" />
3620
+ <copy prop="value" target="c_3" assignNames="c_3a" />
3621
+ <copy prop="value" target="c_4" assignNames="c_4a" />
3622
+ <copy prop="value" target="c_5" assignNames="c_5a" />
3623
+ <copy prop="value" target="c_6" assignNames="c_6a" />
3624
+ <copy prop="value" target="x" assignNames="xa" />
3625
+ </p>
3626
+ `,
3627
+ },
3628
+ "*",
3629
+ );
3630
+ });
3631
+
3632
+ cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded
3633
+
3634
+ function fp(x, c1, c2, c3, c4, c5) {
3635
+ return (
3636
+ (c1 * x ** 4) / 4 -
3637
+ (c1 * (c2 + c3 + c4) * x ** 3) / 3 +
3638
+ (c1 * (c2 * c3 + c2 * c4 + c3 * c4) * x ** 2) / 2 -
3639
+ c1 * c2 * c3 * c4 * x +
3640
+ c5
3641
+ );
3642
+ }
3643
+
3644
+ function fpMinima(c1, c2, c3, c4, c5) {
3645
+ let extrema = [c2, c3, c4].sort((a, b) => a - b);
3646
+ let minima = [];
3647
+ if (c1 > 0) {
3648
+ minima.push([extrema[0], fp(extrema[0], c1, c2, c3, c4, c5)]);
3649
+ minima.push([extrema[2], fp(extrema[2], c1, c2, c3, c4, c5)]);
3650
+ } else {
3651
+ minima.push([extrema[1], fp(extrema[1], c1, c2, c3, c4, c5)]);
3652
+ }
3653
+ return minima;
3654
+ }
3655
+
3656
+ function fpMaxima(c1, c2, c3, c4, c5) {
3657
+ let extrema = [c2, c3, c4].sort((a, b) => a - b);
3658
+ let maxima = [];
3659
+ if (c1 > 0) {
3660
+ maxima.push([extrema[1], fp(extrema[1], c1, c2, c3, c4, c5)]);
3661
+ } else {
3662
+ maxima.push([extrema[0], fp(extrema[0], c1, c2, c3, c4, c5)]);
3663
+ maxima.push([extrema[2], fp(extrema[2], c1, c2, c3, c4, c5)]);
3664
+ }
3665
+ return maxima;
3666
+ }
3667
+
3668
+ cy.window().then(async (win) => {
3669
+ let stateVariables = await win.returnAllStateVariables1();
3670
+
3671
+ function verifyExtrema(c1, c2, c3, c4, c5) {
3672
+ let minima = fpMinima(c1, c2, c3, c4, c5);
3673
+ let nMinima = minima.length;
3674
+ let maxima = fpMaxima(c1, c2, c3, c4, c5);
3675
+ let nMaxima = maxima.length;
3676
+
3677
+ expect(stateVariables[""]);
3678
+
3679
+ cy.get(cesc("#\\/nMinima")).should("have.text", nMinima.toString());
3680
+ cy.get(cesc("#\\/nMinima2")).should("have.text", nMinima.toString());
3681
+ cy.get(cesc("#\\/min1"))
3682
+ .find(".mjx-mrow")
3683
+ .eq(0)
3684
+ .invoke("text")
3685
+ .then((text) => {
3686
+ expect(text.replace(/−/g, "-").trim()).equal(
3687
+ `(${minima[0][0]},${me.math.round(minima[0][1], 5)})`,
3688
+ );
3689
+ });
3690
+ cy.get(cesc("#\\/min12"))
3691
+ .find(".mjx-mrow")
3692
+ .eq(0)
3693
+ .invoke("text")
3694
+ .then((text) => {
3695
+ expect(text.replace(/−/g, "-").trim()).equal(
3696
+ `(${minima[0][0]},${me.math.round(minima[0][1], 5)})`,
3697
+ );
3698
+ });
3699
+ if (nMinima === 2) {
3700
+ cy.get(cesc("#\\/min2"))
3701
+ .find(".mjx-mrow")
3702
+ .eq(0)
3703
+ .invoke("text")
3704
+ .then((text) => {
3705
+ expect(text.replace(/−/g, "-").trim()).equal(
3706
+ `(${minima[1][0]},${me.math.round(minima[1][1], 5)})`,
3707
+ );
3708
+ });
3709
+ cy.get(cesc("#\\/min22"))
3710
+ .find(".mjx-mrow")
3711
+ .eq(0)
3712
+ .invoke("text")
3713
+ .then((text) => {
3714
+ expect(text.replace(/−/g, "-").trim()).equal(
3715
+ `(${minima[1][0]},${me.math.round(minima[1][1], 5)})`,
3716
+ );
3717
+ });
3718
+ } else {
3719
+ cy.get(cesc("#\\/min2")).should("not.exist");
3720
+ cy.get(cesc("#\\/min22")).should("not.exist");
3721
+ }
3722
+ cy.get(cesc("#\\/nMaxima")).should("have.text", nMaxima.toString());
3723
+ cy.get(cesc("#\\/nMaxima2")).should("have.text", nMaxima.toString());
3724
+ cy.get(cesc("#\\/max1"))
3725
+ .find(".mjx-mrow")
3726
+ .eq(0)
3727
+ .invoke("text")
3728
+ .then((text) => {
3729
+ expect(text.replace(/−/g, "-").trim()).equal(
3730
+ `(${maxima[0][0]},${me.math.round(maxima[0][1], 5)})`,
3731
+ );
3732
+ });
3733
+ cy.get(cesc("#\\/max12"))
3734
+ .find(".mjx-mrow")
3735
+ .eq(0)
3736
+ .invoke("text")
3737
+ .then((text) => {
3738
+ expect(text.replace(/−/g, "-").trim()).equal(
3739
+ `(${maxima[0][0]},${me.math.round(maxima[0][1], 5)})`,
3740
+ );
3741
+ });
3742
+ if (nMaxima === 2) {
3743
+ cy.get(cesc("#\\/max2"))
3744
+ .find(".mjx-mrow")
3745
+ .eq(0)
3746
+ .invoke("text")
3747
+ .then((text) => {
3748
+ expect(text.replace(/−/g, "-").trim()).equal(
3749
+ `(${maxima[1][0]},${me.math.round(maxima[1][1], 5)})`,
3750
+ );
3751
+ });
3752
+ cy.get(cesc("#\\/max22"))
3753
+ .find(".mjx-mrow")
3754
+ .eq(0)
3755
+ .invoke("text")
3756
+ .then((text) => {
3757
+ expect(text.replace(/−/g, "-").trim()).equal(
3758
+ `(${maxima[1][0]},${me.math.round(maxima[1][1], 5)})`,
3759
+ );
3760
+ });
3761
+ } else {
3762
+ cy.get(cesc("#\\/max2")).should("not.exist");
3763
+ cy.get(cesc("#\\/max22")).should("not.exist");
3764
+ }
3765
+ }
3766
+
3767
+ let c1 = 1,
3768
+ c2 = 1,
3769
+ c3 = 3,
3770
+ c4 = 4,
3771
+ c5 = 5,
3772
+ c6 = 1,
3773
+ v = "x";
3774
+
3775
+ verifyExtrema(c1, c2, c3, c4, c5);
3776
+
3777
+ cy.window().then(async (win) => {
3778
+ c1 = 3;
3779
+ cy.get(cesc2("#/c_1") + " textarea").type(
3780
+ `{end}{backspace}{backspace}${c1}{enter}`,
3781
+ { force: true },
3782
+ );
3783
+ cy.get(cesc2("#/c_1a")).should("contain.text", nInDOM(c1));
3784
+ verifyExtrema(c1, c2, c3, c4, c5);
3785
+
3786
+ c2 = -5;
3787
+ cy.get(cesc2("#/c_2") + " textarea").type(
3788
+ `{end}{backspace}{backspace}${c2}{enter}`,
3789
+ { force: true },
3790
+ );
3791
+ cy.get(cesc2("#/c_2a")).should("contain.text", nInDOM(c2));
3792
+ verifyExtrema(c1, c2, c3, c4, c5);
3793
+
3794
+ c3 = 1;
3795
+ cy.get(cesc2("#/c_3") + " textarea").type(
3796
+ `{end}{backspace}{backspace}${c3}{enter}`,
3797
+ { force: true },
3798
+ );
3799
+ cy.get(cesc2("#/c_3a")).should("contain.text", nInDOM(c3));
3800
+ verifyExtrema(c1, c2, c3, c4, c5);
3801
+
3802
+ c4 = -6;
3803
+ cy.get(cesc2("#/c_4") + " textarea").type(
3804
+ `{end}{backspace}{backspace}${c4}{enter}`,
3805
+ { force: true },
3806
+ );
3807
+ cy.get(cesc2("#/c_4a")).should("contain.text", nInDOM(c4));
3808
+ verifyExtrema(c1, c2, c3, c4, c5);
3809
+
3810
+ c5 = 3;
3811
+ cy.get(cesc2("#/c_5") + " textarea").type(
3812
+ `{end}{backspace}{backspace}${c5}{enter}`,
3813
+ { force: true },
3814
+ );
3815
+ cy.get(cesc2("#/c_5a")).should("contain.text", nInDOM(c5));
3816
+ verifyExtrema(c1, c2, c3, c4, c5);
3817
+
3818
+ c6 = 2;
3819
+ cy.get(cesc2("#/c_6") + " textarea").type(
3820
+ `{end}{backspace}{backspace}${c6}{enter}`,
3821
+ { force: true },
3822
+ );
3823
+ cy.get(cesc2("#/c_6a")).should("contain.text", nInDOM(c6));
3824
+ verifyExtrema(c1, c2, c3, c4, c5);
3825
+
3826
+ v = "y";
3827
+ cy.get(cesc2("#/x") + " textarea").type(
3828
+ `{end}{backspace}{backspace}${v}{enter}`,
3829
+ { force: true },
3830
+ );
3831
+ cy.get(cesc2("#/xa")).should("contain.text", v);
3832
+ verifyExtrema(c1, c2, c3, c4, c5);
3833
+ });
3834
+
3835
+ cy.window().then(async (win) => {
3836
+ c1 = 2;
3837
+ cy.get(cesc2("#/c_1") + " textarea").type(
3838
+ `{end}{backspace}{backspace}${c1}{enter}`,
3839
+ { force: true },
3840
+ );
3841
+ cy.get(cesc2("#/c_1a")).should("contain.text", nInDOM(c1));
3842
+ verifyExtrema(c1, c2, c3, c4, c5);
3843
+
3844
+ c2 = 4;
3845
+ cy.get(cesc2("#/c_2") + " textarea").type(
3846
+ `{end}{backspace}{backspace}${c2}{enter}`,
3847
+ { force: true },
3848
+ );
3849
+ cy.get(cesc2("#/c_2a")).should("contain.text", nInDOM(c2));
3850
+ verifyExtrema(c1, c2, c3, c4, c5);
3851
+
3852
+ c3 = -8;
3853
+ cy.get(cesc2("#/c_3") + " textarea").type(
3854
+ `{end}{backspace}{backspace}${c3}{enter}`,
3855
+ { force: true },
3856
+ );
3857
+ cy.get(cesc2("#/c_3a")).should("contain.text", nInDOM(c3));
3858
+ verifyExtrema(c1, c2, c3, c4, c5);
3859
+
3860
+ c4 = 9;
3861
+ cy.get(cesc2("#/c_4") + " textarea").type(
3862
+ `{end}{backspace}{backspace}${c4}{enter}`,
3863
+ { force: true },
3864
+ );
3865
+ cy.get(cesc2("#/c_4a")).should("contain.text", nInDOM(c4));
3866
+ verifyExtrema(c1, c2, c3, c4, c5);
3867
+
3868
+ c5 = -2;
3869
+ cy.get(cesc2("#/c_5") + " textarea").type(
3870
+ `{end}{backspace}{backspace}${c5}{enter}`,
3871
+ { force: true },
3872
+ );
3873
+ cy.get(cesc2("#/c_5a")).should("contain.text", nInDOM(c5));
3874
+ verifyExtrema(c1, c2, c3, c4, c5);
3875
+
3876
+ c6 = 6;
3877
+ cy.get(cesc2("#/c_6") + " textarea").type(
3878
+ `{end}{backspace}{backspace}${c6}{enter}`,
3879
+ { force: true },
3880
+ );
3881
+ cy.get(cesc2("#/c_6a")).should("contain.text", nInDOM(c6));
3882
+ verifyExtrema(c1, c2, c3, c4, c5);
3883
+
3884
+ v = "q";
3885
+ cy.get(cesc2("#/x") + " textarea").type(
3886
+ `{end}{backspace}{backspace}${v}{enter}`,
3887
+ { force: true },
3888
+ );
3889
+ cy.get(cesc2("#/xa")).should("contain.text", v);
3890
+ verifyExtrema(c1, c2, c3, c4, c5);
3891
+ });
3892
+ });
3893
+ });
3894
+
3895
+ it("extrema of derivative of interpolated function", () => {
3896
+ cy.window().then(async (win) => {
3897
+ win.postMessage(
3898
+ {
3899
+ doenetML: `
3900
+ <text>a</text>
3901
+ <graph>
3902
+ <function name="f" minima="(-5,-3) (0,-5)" maxima="(-3,0) (6,8)" />
3903
+ <derivative name="fp" stylenumber="2"><copy target="f"/></derivative>
3904
+ </graph>
3905
+
3906
+ <copy target="fp" name="fp2" />
3907
+
3908
+ <p>Number of minima of f': <copy prop="numMinima" assignNames="nMinima" target="fp" /></p>
3909
+ <p>Minima of f': <extract prop="coords" displayDecimals="5" assignNames="min1 min2"><copy prop="minima" target="fp" /></extract></p>
3910
+
3911
+ <p>Number of maxima of f': <copy prop="numMaxima" assignNames="nMaxima" target="fp" /></p>
3912
+ <p>Maxima of f': <extract prop="coords" displayDecimals="5" assignNames="max1 max2"><copy prop="maxima" target="fp" /></extract></p>
3913
+
3914
+ <p>To repeat:</p>
3915
+ <p>Number of minima of f': <copy prop="numMinima" assignNames="nMinima2" target="fp2" /></p>
3916
+ <p>Minima of f': <extract prop="coords" displayDecimals="5" assignNames="min12 min22"><copy prop="minima" target="fp2" /></extract></p>
3917
+
3918
+ <p>Number of maxima of f': <copy prop="numMaxima" assignNames="nMaxima2" target="fp2" /></p>
3919
+ <p>Maxima of f': <extract prop="coords" displayDecimals="5" assignNames="max12 max22"><copy prop="maxima" target="fp2" /></extract></p>
3920
+
3921
+ `,
3922
+ },
3923
+ "*",
3924
+ );
3925
+ });
3926
+
3927
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded
3928
+
3929
+ cy.get(cesc("#\\/nMinima")).should("have.text", "1");
3930
+ cy.get(cesc("#\\/nMinima2")).should("have.text", "1");
3931
+
3932
+ cy.get(cesc("#\\/nMaxima")).should("have.text", "2");
3933
+ cy.get(cesc("#\\/nMaxima2")).should("have.text", "2");
3934
+
3935
+ cy.window().then(async (win) => {
3936
+ let stateVariables = await win.returnAllStateVariables1();
3937
+
3938
+ let fp = createFunctionFromDefinition(
3939
+ stateVariables["/fp"].stateValues.fDefinitions[0],
3940
+ );
3941
+
3942
+ let max1x = (-5 - 3) / 2;
3943
+ cy.get(cesc("#\\/max1"))
3944
+ .find(".mjx-mrow")
3945
+ .eq(0)
3946
+ .invoke("text")
3947
+ .then((text) => {
3948
+ expect(text.replace(/−/g, "-").trim()).equal(
3949
+ `(${max1x},${me.math.round(fp(max1x), 5)})`,
3950
+ );
3951
+ });
3952
+ cy.get(cesc("#\\/max12"))
3953
+ .find(".mjx-mrow")
3954
+ .eq(0)
3955
+ .invoke("text")
3956
+ .then((text) => {
3957
+ expect(text.replace(/−/g, "-").trim()).equal(
3958
+ `(${max1x},${me.math.round(fp(max1x), 5)})`,
3959
+ );
3960
+ });
3961
+
3962
+ let min1x = (-3 + 0) / 2;
3963
+ cy.get(cesc("#\\/min1"))
3964
+ .find(".mjx-mrow")
3965
+ .eq(0)
3966
+ .invoke("text")
3967
+ .then((text) => {
3968
+ expect(text.replace(/−/g, "-").trim()).equal(
3969
+ `(${min1x},${me.math.round(fp(min1x), 5)})`,
3970
+ );
3971
+ });
3972
+ cy.get(cesc("#\\/min12"))
3973
+ .find(".mjx-mrow")
3974
+ .eq(0)
3975
+ .invoke("text")
3976
+ .then((text) => {
3977
+ expect(text.replace(/−/g, "-").trim()).equal(
3978
+ `(${min1x},${me.math.round(fp(min1x), 5)})`,
3979
+ );
3980
+ });
3981
+
3982
+ let max2x = (0 + 6) / 2;
3983
+ cy.get(cesc("#\\/max2"))
3984
+ .find(".mjx-mrow")
3985
+ .eq(0)
3986
+ .invoke("text")
3987
+ .then((text) => {
3988
+ expect(text.replace(/−/g, "-").trim()).equal(
3989
+ `(${max2x},${me.math.round(fp(max2x), 5)})`,
3990
+ );
3991
+ });
3992
+ cy.get(cesc("#\\/max22"))
3993
+ .find(".mjx-mrow")
3994
+ .eq(0)
3995
+ .invoke("text")
3996
+ .then((text) => {
3997
+ expect(text.replace(/−/g, "-").trim()).equal(
3998
+ `(${max2x},${me.math.round(fp(max2x), 5)})`,
3999
+ );
4000
+ });
4001
+ });
4002
+ });
4003
+
4004
+ it("handle no child", () => {
4005
+ cy.window().then(async (win) => {
4006
+ win.postMessage(
4007
+ {
4008
+ doenetML: `
4009
+ <derivative name="d1" symbolic></derivative>
4010
+ <derivative name="d2">$nothing</derivative>
4011
+
4012
+ <p>$$d1(0)</p>
4013
+ <p>$$d2(0)</p>
4014
+ `,
4015
+ },
4016
+ "*",
4017
+ );
4018
+ });
4019
+
4020
+ cy.get(cesc("#\\/d1") + " .mjx-mrow")
4021
+ .eq(0)
4022
+ .should("have.text", "\uff3f");
4023
+ cy.get(cesc("#\\/d2") + " .mjx-mrow")
4024
+ .eq(0)
4025
+ .should("have.text", "\uff3f");
4026
+ cy.get(cesc("#\\/_p1") + " .mjx-mrow")
4027
+ .eq(0)
4028
+ .should("have.text", "NaN");
4029
+ cy.get(cesc("#\\/_p2") + " .mjx-mrow")
4030
+ .eq(0)
4031
+ .should("have.text", "NaN");
4032
+
4033
+ cy.window().then(async (win) => {
4034
+ let stateVariables = await win.returnAllStateVariables1();
4035
+
4036
+ let d1 = createFunctionFromDefinition(
4037
+ stateVariables["/d1"].stateValues.fDefinitions[0],
4038
+ );
4039
+ let d2 = createFunctionFromDefinition(
4040
+ stateVariables["/d2"].stateValues.fDefinitions[0],
4041
+ );
4042
+
4043
+ expect(d1(0)).eqls(NaN);
4044
+ expect(d2(0)).eqls(NaN);
4045
+ });
4046
+ });
4047
+ });