@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,4749 @@
1
+ import me from "math-expressions";
2
+ import { cesc, cesc2 } from "../../../../src/utils/url";
3
+
4
+ function nInDOM(n) {
5
+ if (n < 0) {
6
+ return `−${Math.abs(n)}`;
7
+ } else {
8
+ return String(n);
9
+ }
10
+ }
11
+
12
+ async function testLineSegmentCopiedTwice({
13
+ x1,
14
+ y1,
15
+ x2,
16
+ y2,
17
+ lineSegmentName = "/ls",
18
+ graph1Name = "/g1",
19
+ graph2Name = "/g2",
20
+ graph3Name = "/g3",
21
+ point1InDomName = "/p1",
22
+ point2InDomName = "/p2",
23
+ }) {
24
+ cy.get(`#${cesc2(point1InDomName)} .mjx-mrow`).should(
25
+ "contain.text",
26
+ `(${nInDOM(x1)},${nInDOM(y1)})`,
27
+ );
28
+ cy.get(`#${cesc2(point2InDomName)} .mjx-mrow`).should(
29
+ "contain.text",
30
+ `(${nInDOM(x2)},${nInDOM(y2)})`,
31
+ );
32
+
33
+ cy.window().then(async (win) => {
34
+ let stateVariables = await win.returnAllStateVariables1();
35
+ expect(
36
+ stateVariables[graph1Name + lineSegmentName].stateValues.endpoints[0],
37
+ ).eqls([x1, y1]);
38
+ expect(
39
+ stateVariables[graph1Name + lineSegmentName].stateValues.endpoints[1],
40
+ ).eqls([x2, y2]);
41
+ expect(
42
+ stateVariables[graph2Name + lineSegmentName].stateValues.endpoints[0],
43
+ ).eqls([x1, y1]);
44
+ expect(
45
+ stateVariables[graph2Name + lineSegmentName].stateValues.endpoints[1],
46
+ ).eqls([x2, y2]);
47
+ expect(
48
+ stateVariables[graph3Name + lineSegmentName].stateValues.endpoints[0],
49
+ ).eqls([x1, y1]);
50
+ expect(
51
+ stateVariables[graph3Name + lineSegmentName].stateValues.endpoints[1],
52
+ ).eqls([x2, y2]);
53
+ });
54
+ }
55
+
56
+ async function testLineSegmentCopiedTwiceWithEndpoints({
57
+ x1,
58
+ y1,
59
+ x2,
60
+ y2,
61
+ lineSegmentName = "/ls",
62
+ endpoint1Name = "/A",
63
+ endpoint2Name = "/B",
64
+ graph1Name = "/g1",
65
+ graph2Name = "/g2",
66
+ graph3Name = "/g3",
67
+ point1InDomName = "/p1",
68
+ point2InDomName = "/p2",
69
+ }) {
70
+ cy.get(`#${cesc2(point1InDomName)} .mjx-mrow`).should(
71
+ "contain.text",
72
+ `(${nInDOM(x1)},${nInDOM(y1)})`,
73
+ );
74
+ cy.get(`#${cesc2(point2InDomName)} .mjx-mrow`).should(
75
+ "contain.text",
76
+ `(${nInDOM(x2)},${nInDOM(y2)})`,
77
+ );
78
+
79
+ cy.window().then(async (win) => {
80
+ let stateVariables = await win.returnAllStateVariables1();
81
+ expect(
82
+ stateVariables[graph1Name + lineSegmentName].stateValues.endpoints[0],
83
+ ).eqls([x1, y1]);
84
+ expect(
85
+ stateVariables[graph1Name + lineSegmentName].stateValues.endpoints[1],
86
+ ).eqls([x2, y2]);
87
+ expect(
88
+ stateVariables[graph2Name + lineSegmentName].stateValues.endpoints[0],
89
+ ).eqls([x1, y1]);
90
+ expect(
91
+ stateVariables[graph2Name + lineSegmentName].stateValues.endpoints[1],
92
+ ).eqls([x2, y2]);
93
+ expect(
94
+ stateVariables[graph3Name + lineSegmentName].stateValues.endpoints[0],
95
+ ).eqls([x1, y1]);
96
+ expect(
97
+ stateVariables[graph3Name + lineSegmentName].stateValues.endpoints[1],
98
+ ).eqls([x2, y2]);
99
+ expect(stateVariables[graph1Name + endpoint1Name].stateValues.coords).eqls([
100
+ "vector",
101
+ x1,
102
+ y1,
103
+ ]);
104
+ expect(stateVariables[graph1Name + endpoint2Name].stateValues.coords).eqls([
105
+ "vector",
106
+ x2,
107
+ y2,
108
+ ]);
109
+ expect(stateVariables[graph2Name + endpoint1Name].stateValues.coords).eqls([
110
+ "vector",
111
+ x1,
112
+ y1,
113
+ ]);
114
+ expect(stateVariables[graph2Name + endpoint2Name].stateValues.coords).eqls([
115
+ "vector",
116
+ x2,
117
+ y2,
118
+ ]);
119
+ expect(stateVariables[graph3Name + endpoint1Name].stateValues.coords).eqls([
120
+ "vector",
121
+ x1,
122
+ y1,
123
+ ]);
124
+ expect(stateVariables[graph3Name + endpoint2Name].stateValues.coords).eqls([
125
+ "vector",
126
+ x2,
127
+ y2,
128
+ ]);
129
+ });
130
+ }
131
+
132
+ describe("LineSegment Tag Tests", function () {
133
+ beforeEach(() => {
134
+ cy.clearIndexedDB();
135
+ cy.visit("/src/Tools/cypressTest/");
136
+ });
137
+
138
+ it("lineSegment with no arguments", () => {
139
+ cy.window().then(async (win) => {
140
+ win.postMessage(
141
+ {
142
+ doenetML: `
143
+ <text>a</text>
144
+ <graph name="g1" newNamespace>
145
+ <lineSegment name="ls"/>
146
+ </graph>
147
+
148
+ <graph name="g2" newNamespace>
149
+ <copy assignNames="ls" target="../g1/ls" />
150
+ </graph>
151
+
152
+ <copy assignNames="g3" target="g2" />
153
+
154
+ <copy prop="endpoint1" target="g1/ls" assignNames="p1" />
155
+ <copy prop="endpoint2" target="g1/ls" assignNames="p2" />
156
+ `,
157
+ },
158
+ "*",
159
+ );
160
+ });
161
+
162
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
163
+
164
+ let x1 = 1,
165
+ y1 = 0;
166
+ let x2 = 0,
167
+ y2 = 0;
168
+
169
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
170
+
171
+ cy.log("move original first point");
172
+ cy.window().then(async (win) => {
173
+ x1 = 3;
174
+ y1 = -5;
175
+
176
+ win.callAction1({
177
+ actionName: "moveLineSegment",
178
+ componentName: "/g1/ls",
179
+ args: {
180
+ point1coords: [x1, y1],
181
+ },
182
+ });
183
+
184
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
185
+ });
186
+
187
+ cy.log("move copied second point");
188
+ cy.window().then(async (win) => {
189
+ x2 = -7;
190
+ y2 = -5;
191
+
192
+ win.callAction1({
193
+ actionName: "moveLineSegment",
194
+ componentName: "/g1/ls",
195
+ args: {
196
+ point2coords: [x2, y2],
197
+ },
198
+ });
199
+
200
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
201
+ });
202
+
203
+ cy.log("move copied first point");
204
+ cy.window().then(async (win) => {
205
+ x1 = 6;
206
+ y1 = 0;
207
+
208
+ win.callAction1({
209
+ actionName: "moveLineSegment",
210
+ componentName: "/g2/ls",
211
+ args: {
212
+ point1coords: [x1, y1],
213
+ },
214
+ });
215
+
216
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
217
+ });
218
+
219
+ cy.log("move copied second point");
220
+ cy.window().then(async (win) => {
221
+ x2 = 9;
222
+ y2 = -8;
223
+
224
+ win.callAction1({
225
+ actionName: "moveLineSegment",
226
+ componentName: "/g2/ls",
227
+ args: {
228
+ point2coords: [x2, y2],
229
+ },
230
+ });
231
+
232
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
233
+ });
234
+
235
+ cy.log("move double copied first point");
236
+ cy.window().then(async (win) => {
237
+ x1 = -5;
238
+ y1 = 7;
239
+
240
+ win.callAction1({
241
+ actionName: "moveLineSegment",
242
+ componentName: "/g3/ls",
243
+ args: {
244
+ point1coords: [x1, y1],
245
+ },
246
+ });
247
+
248
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
249
+ });
250
+
251
+ cy.log("move double copied second point");
252
+ cy.window().then(async (win) => {
253
+ x2 = -1;
254
+ y2 = 3;
255
+
256
+ win.callAction1({
257
+ actionName: "moveLineSegment",
258
+ componentName: "/g3/ls",
259
+ args: {
260
+ point2coords: [x2, y2],
261
+ },
262
+ });
263
+
264
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
265
+ });
266
+ });
267
+
268
+ it("lineSegment with empty endpoints", () => {
269
+ cy.window().then(async (win) => {
270
+ win.postMessage(
271
+ {
272
+ doenetML: `
273
+ <text>a</text>
274
+ <graph name="g1" newNamespace>
275
+ <lineSegment name="ls" endpoints="" />
276
+ </graph>
277
+
278
+ <graph name="g2" newNamespace>
279
+ <copy assignNames="ls" target="../g1/ls" />
280
+ </graph>
281
+
282
+ <copy assignNames="g3" target="g2" />
283
+
284
+ <copy prop="endpoint1" target="g1/ls" assignNames="p1" />
285
+ <copy prop="endpoint2" target="g1/ls" assignNames="p2" />
286
+ `,
287
+ },
288
+ "*",
289
+ );
290
+ });
291
+
292
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
293
+
294
+ let x1 = 1,
295
+ y1 = 0;
296
+ let x2 = 0,
297
+ y2 = 0;
298
+
299
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
300
+
301
+ cy.log("move original first point");
302
+ cy.window().then(async (win) => {
303
+ x1 = 3;
304
+ y1 = -5;
305
+
306
+ win.callAction1({
307
+ actionName: "moveLineSegment",
308
+ componentName: "/g1/ls",
309
+ args: {
310
+ point1coords: [x1, y1],
311
+ },
312
+ });
313
+
314
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
315
+ });
316
+
317
+ cy.log("move copied second point");
318
+ cy.window().then(async (win) => {
319
+ x2 = -7;
320
+ y2 = -5;
321
+
322
+ win.callAction1({
323
+ actionName: "moveLineSegment",
324
+ componentName: "/g1/ls",
325
+ args: {
326
+ point2coords: [x2, y2],
327
+ },
328
+ });
329
+
330
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
331
+ });
332
+
333
+ cy.log("move copied first point");
334
+ cy.window().then(async (win) => {
335
+ x1 = 6;
336
+ y1 = 0;
337
+
338
+ win.callAction1({
339
+ actionName: "moveLineSegment",
340
+ componentName: "/g2/ls",
341
+ args: {
342
+ point1coords: [x1, y1],
343
+ },
344
+ });
345
+
346
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
347
+ });
348
+
349
+ cy.log("move copied second point");
350
+ cy.window().then(async (win) => {
351
+ x2 = 9;
352
+ y2 = -8;
353
+
354
+ win.callAction1({
355
+ actionName: "moveLineSegment",
356
+ componentName: "/g2/ls",
357
+ args: {
358
+ point2coords: [x2, y2],
359
+ },
360
+ });
361
+
362
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
363
+ });
364
+
365
+ cy.log("move double copied first point");
366
+ cy.window().then(async (win) => {
367
+ x1 = -5;
368
+ y1 = 7;
369
+
370
+ win.callAction1({
371
+ actionName: "moveLineSegment",
372
+ componentName: "/g3/ls",
373
+ args: {
374
+ point1coords: [x1, y1],
375
+ },
376
+ });
377
+
378
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
379
+ });
380
+
381
+ cy.log("move double copied second point");
382
+ cy.window().then(async (win) => {
383
+ x2 = -1;
384
+ y2 = 3;
385
+
386
+ win.callAction1({
387
+ actionName: "moveLineSegment",
388
+ componentName: "/g3/ls",
389
+ args: {
390
+ point2coords: [x2, y2],
391
+ },
392
+ });
393
+
394
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
395
+ });
396
+ });
397
+
398
+ it("lineSegment with one point", () => {
399
+ cy.window().then(async (win) => {
400
+ win.postMessage(
401
+ {
402
+ doenetML: `
403
+ <text>a</text>
404
+ <graph name="g1" newNamespace>
405
+ <lineSegment endpoints="(3,-8)" name="ls"/>
406
+ </graph>
407
+
408
+ <graph name="g2" newNamespace>
409
+ <copy assignNames="ls" target="../g1/ls" />
410
+ </graph>
411
+
412
+ <copy assignNames="g3" target="g2" />
413
+
414
+ <copy prop="endpoint1" target="g1/ls" assignNames="p1" />
415
+ <copy prop="endpoint2" target="g1/ls" assignNames="p2" />
416
+ `,
417
+ },
418
+ "*",
419
+ );
420
+ });
421
+
422
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
423
+
424
+ let x1 = 3,
425
+ y1 = -8;
426
+ let x2 = 0,
427
+ y2 = 0;
428
+
429
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
430
+
431
+ cy.log("move original first point");
432
+ cy.window().then(async (win) => {
433
+ x1 = 3;
434
+ y1 = -5;
435
+
436
+ win.callAction1({
437
+ actionName: "moveLineSegment",
438
+ componentName: "/g1/ls",
439
+ args: {
440
+ point1coords: [x1, y1],
441
+ },
442
+ });
443
+
444
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
445
+ });
446
+
447
+ cy.log("move copied second point");
448
+ cy.window().then(async (win) => {
449
+ x2 = -7;
450
+ y2 = -5;
451
+
452
+ win.callAction1({
453
+ actionName: "moveLineSegment",
454
+ componentName: "/g1/ls",
455
+ args: {
456
+ point2coords: [x2, y2],
457
+ },
458
+ });
459
+
460
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
461
+ });
462
+
463
+ cy.log("move copied first point");
464
+ cy.window().then(async (win) => {
465
+ x1 = 6;
466
+ y1 = 0;
467
+
468
+ win.callAction1({
469
+ actionName: "moveLineSegment",
470
+ componentName: "/g2/ls",
471
+ args: {
472
+ point1coords: [x1, y1],
473
+ },
474
+ });
475
+
476
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
477
+ });
478
+
479
+ cy.log("move copied second point");
480
+ cy.window().then(async (win) => {
481
+ x2 = 9;
482
+ y2 = -8;
483
+
484
+ win.callAction1({
485
+ actionName: "moveLineSegment",
486
+ componentName: "/g2/ls",
487
+ args: {
488
+ point2coords: [x2, y2],
489
+ },
490
+ });
491
+
492
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
493
+ });
494
+
495
+ cy.log("move double copied first point");
496
+ cy.window().then(async (win) => {
497
+ x1 = -5;
498
+ y1 = 7;
499
+
500
+ win.callAction1({
501
+ actionName: "moveLineSegment",
502
+ componentName: "/g3/ls",
503
+ args: {
504
+ point1coords: [x1, y1],
505
+ },
506
+ });
507
+
508
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
509
+ });
510
+
511
+ cy.log("move double copied second point");
512
+ cy.window().then(async (win) => {
513
+ x2 = -1;
514
+ y2 = 3;
515
+
516
+ win.callAction1({
517
+ actionName: "moveLineSegment",
518
+ componentName: "/g3/ls",
519
+ args: {
520
+ point2coords: [x2, y2],
521
+ },
522
+ });
523
+
524
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
525
+ });
526
+ });
527
+
528
+ it("lineSegment with one point - the origin", () => {
529
+ cy.window().then(async (win) => {
530
+ win.postMessage(
531
+ {
532
+ doenetML: `
533
+ <text>a</text>
534
+ <graph name="g1" newNamespace>
535
+ <lineSegment endpoints="(0,0)" name="ls"/>
536
+ </graph>
537
+
538
+ <graph name="g2" newNamespace>
539
+ <copy assignNames="ls" target="../g1/ls" />
540
+ </graph>
541
+
542
+ <copy assignNames="g3" target="g2" />
543
+
544
+ <copy prop="endpoint1" target="g1/ls" assignNames="p1" />
545
+ <copy prop="endpoint2" target="g1/ls" assignNames="p2" />
546
+ `,
547
+ },
548
+ "*",
549
+ );
550
+ });
551
+
552
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
553
+
554
+ let x1 = 0,
555
+ y1 = 0;
556
+ let x2 = 0,
557
+ y2 = 0;
558
+
559
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
560
+
561
+ cy.log("move original first point");
562
+ cy.window().then(async (win) => {
563
+ x1 = 3;
564
+ y1 = -5;
565
+
566
+ win.callAction1({
567
+ actionName: "moveLineSegment",
568
+ componentName: "/g1/ls",
569
+ args: {
570
+ point1coords: [x1, y1],
571
+ },
572
+ });
573
+
574
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
575
+ });
576
+
577
+ cy.log("move copied second point");
578
+ cy.window().then(async (win) => {
579
+ x2 = -7;
580
+ y2 = -5;
581
+
582
+ win.callAction1({
583
+ actionName: "moveLineSegment",
584
+ componentName: "/g1/ls",
585
+ args: {
586
+ point2coords: [x2, y2],
587
+ },
588
+ });
589
+
590
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
591
+ });
592
+
593
+ cy.log("move copied first point");
594
+ cy.window().then(async (win) => {
595
+ x1 = 6;
596
+ y1 = 0;
597
+
598
+ win.callAction1({
599
+ actionName: "moveLineSegment",
600
+ componentName: "/g2/ls",
601
+ args: {
602
+ point1coords: [x1, y1],
603
+ },
604
+ });
605
+
606
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
607
+ });
608
+
609
+ cy.log("move copied second point");
610
+ cy.window().then(async (win) => {
611
+ x2 = 9;
612
+ y2 = -8;
613
+
614
+ win.callAction1({
615
+ actionName: "moveLineSegment",
616
+ componentName: "/g2/ls",
617
+ args: {
618
+ point2coords: [x2, y2],
619
+ },
620
+ });
621
+
622
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
623
+ });
624
+
625
+ cy.log("move double copied first point");
626
+ cy.window().then(async (win) => {
627
+ x1 = -5;
628
+ y1 = 7;
629
+
630
+ win.callAction1({
631
+ actionName: "moveLineSegment",
632
+ componentName: "/g3/ls",
633
+ args: {
634
+ point1coords: [x1, y1],
635
+ },
636
+ });
637
+
638
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
639
+ });
640
+
641
+ cy.log("move double copied second point");
642
+ cy.window().then(async (win) => {
643
+ x2 = -1;
644
+ y2 = 3;
645
+
646
+ win.callAction1({
647
+ actionName: "moveLineSegment",
648
+ componentName: "/g3/ls",
649
+ args: {
650
+ point2coords: [x2, y2],
651
+ },
652
+ });
653
+
654
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
655
+ });
656
+ });
657
+
658
+ it("lineSegment with copied points", () => {
659
+ cy.window().then(async (win) => {
660
+ win.postMessage(
661
+ {
662
+ doenetML: `
663
+ <text>a</text>
664
+ <graph name="g1" newNamespace>
665
+ <point labelIsName name="A">(3,5)</point>
666
+ <point labelIsName name="B">(-4,-1)</point>
667
+ <lineSegment endpoints="$A $B" name="ls"/>
668
+ </graph>
669
+
670
+ <graph name="g2" newNamespace>
671
+ <copy assignNames="ls" target="../g1/ls" />
672
+ <copy prop="endpoint1" target="ls" assignNames="A" />
673
+ <copy prop="endpoint2" target="ls" assignNames="B" />
674
+ </graph>
675
+
676
+ <copy assignNames="g3" target="g2" />
677
+
678
+ <copy prop="endpoint1" target="g1/ls" assignNames="p1" />
679
+ <copy prop="endpoint2" target="g1/ls" assignNames="p2" />
680
+ `,
681
+ },
682
+ "*",
683
+ );
684
+ });
685
+
686
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
687
+
688
+ let x1 = 3,
689
+ y1 = 5;
690
+ let x2 = -4,
691
+ y2 = -1;
692
+
693
+ testLineSegmentCopiedTwiceWithEndpoints({ x1, y1, x2, y2 });
694
+
695
+ cy.log("move point A to (5,-5)");
696
+ cy.window().then(async (win) => {
697
+ x1 = 5;
698
+ y1 = -5;
699
+
700
+ win.callAction1({
701
+ actionName: "movePoint",
702
+ componentName: "/g1/A",
703
+ args: { x: x1, y: y1 },
704
+ });
705
+
706
+ testLineSegmentCopiedTwiceWithEndpoints({ x1, y1, x2, y2 });
707
+ });
708
+
709
+ cy.log("move line segment up and to the right");
710
+ cy.window().then(async (win) => {
711
+ let moveX = 3;
712
+ let moveY = 2;
713
+
714
+ x1 += moveX;
715
+ x2 += moveX;
716
+ y1 += moveY;
717
+ y2 += moveY;
718
+
719
+ win.callAction1({
720
+ actionName: "moveLineSegment",
721
+ componentName: "/g1/ls",
722
+ args: {
723
+ point1coords: [x1, y1],
724
+ point2coords: [x2, y2],
725
+ },
726
+ });
727
+
728
+ testLineSegmentCopiedTwiceWithEndpoints({ x1, y1, x2, y2 });
729
+ });
730
+
731
+ cy.log("move second copy of B to (-1,8)");
732
+ cy.window().then(async (win) => {
733
+ x2 = -1;
734
+ y2 = 8;
735
+
736
+ win.callAction1({
737
+ actionName: "movePoint",
738
+ componentName: "/g3/B",
739
+ args: { x: x2, y: y2 },
740
+ });
741
+
742
+ testLineSegmentCopiedTwiceWithEndpoints({ x1, y1, x2, y2 });
743
+ });
744
+ });
745
+
746
+ it("lineSegment with endpoints containing sugared string", () => {
747
+ cy.window().then(async (win) => {
748
+ win.postMessage(
749
+ {
750
+ doenetML: `
751
+ <text>a</text>
752
+ <graph name="g1" newNamespace>
753
+ <lineSegment endpoints="(3,5) (-4,9)" name="ls"/>
754
+ </graph>
755
+
756
+ <graph name="g2" newNamespace>
757
+ <copy assignNames="ls" target="../g1/ls" />
758
+ </graph>
759
+
760
+ <copy assignNames="g3" target="g2" />
761
+
762
+ <copy prop="endpoint1" target="g1/ls" assignNames="p1" />
763
+ <copy prop="endpoint2" target="g1/ls" assignNames="p2" />
764
+ `,
765
+ },
766
+ "*",
767
+ );
768
+ });
769
+
770
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
771
+
772
+ let x1 = 3,
773
+ y1 = 5;
774
+ let x2 = -4,
775
+ y2 = 9;
776
+
777
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
778
+
779
+ cy.log("move original first point");
780
+ cy.window().then(async (win) => {
781
+ x1 = 3;
782
+ y1 = -5;
783
+
784
+ win.callAction1({
785
+ actionName: "moveLineSegment",
786
+ componentName: "/g1/ls",
787
+ args: {
788
+ point1coords: [x1, y1],
789
+ },
790
+ });
791
+
792
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
793
+ });
794
+
795
+ cy.log("move copied second point");
796
+ cy.window().then(async (win) => {
797
+ x2 = -7;
798
+ y2 = -5;
799
+
800
+ win.callAction1({
801
+ actionName: "moveLineSegment",
802
+ componentName: "/g1/ls",
803
+ args: {
804
+ point2coords: [x2, y2],
805
+ },
806
+ });
807
+
808
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
809
+ });
810
+
811
+ cy.log("move copied first point");
812
+ cy.window().then(async (win) => {
813
+ x1 = 6;
814
+ y1 = 0;
815
+
816
+ win.callAction1({
817
+ actionName: "moveLineSegment",
818
+ componentName: "/g2/ls",
819
+ args: {
820
+ point1coords: [x1, y1],
821
+ },
822
+ });
823
+
824
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
825
+ });
826
+
827
+ cy.log("move copied second point");
828
+ cy.window().then(async (win) => {
829
+ x2 = 9;
830
+ y2 = -8;
831
+
832
+ win.callAction1({
833
+ actionName: "moveLineSegment",
834
+ componentName: "/g2/ls",
835
+ args: {
836
+ point2coords: [x2, y2],
837
+ },
838
+ });
839
+
840
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
841
+ });
842
+
843
+ cy.log("move double copied first point");
844
+ cy.window().then(async (win) => {
845
+ x1 = -5;
846
+ y1 = 7;
847
+
848
+ win.callAction1({
849
+ actionName: "moveLineSegment",
850
+ componentName: "/g3/ls",
851
+ args: {
852
+ point1coords: [x1, y1],
853
+ },
854
+ });
855
+
856
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
857
+ });
858
+
859
+ cy.log("move double copied second point");
860
+ cy.window().then(async (win) => {
861
+ x2 = -1;
862
+ y2 = 3;
863
+
864
+ win.callAction1({
865
+ actionName: "moveLineSegment",
866
+ componentName: "/g3/ls",
867
+ args: {
868
+ point2coords: [x2, y2],
869
+ },
870
+ });
871
+
872
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
873
+ });
874
+ });
875
+
876
+ it("lineSegment with strings and copies", () => {
877
+ cy.window().then(async (win) => {
878
+ win.postMessage(
879
+ {
880
+ doenetML: `
881
+ <text>a</text>
882
+ <number>3</number>
883
+ <graph>
884
+ <linesegment />
885
+ </graph>
886
+ <graph name="g1" newNamespace>
887
+ <point>(-2,1)</point>
888
+ <lineSegment endpoints="($(../_number1), $(_point1.x)) ($(_point1.y),5)" name="ls"/>
889
+ </graph>
890
+
891
+ <graph name="g2" newNamespace>
892
+ <copy assignNames="ls" target="../g1/ls" />
893
+ </graph>
894
+
895
+ <copy assignNames="g3" target="g2" />
896
+
897
+ <copy prop="endpoint1" target="g1/ls" assignNames="p1" />
898
+ <copy prop="endpoint2" target="g1/ls" assignNames="p2" />
899
+ `,
900
+ },
901
+ "*",
902
+ );
903
+ });
904
+
905
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
906
+
907
+ let x1 = 3,
908
+ y1 = -2;
909
+ let x2 = 1,
910
+ y2 = 5;
911
+
912
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
913
+
914
+ cy.window().then(async (win) => {
915
+ let stateVariables = await win.returnAllStateVariables1();
916
+ expect(stateVariables["/g1/_point1"].stateValues.xs).eqls([-2, 1]);
917
+ expect(stateVariables["/_number1"].stateValues.value).eq(3);
918
+ });
919
+
920
+ cy.log("move original first point");
921
+ cy.window().then(async (win) => {
922
+ x1 = 3;
923
+ y1 = -5;
924
+
925
+ win.callAction1({
926
+ actionName: "moveLineSegment",
927
+ componentName: "/g1/ls",
928
+ args: {
929
+ point1coords: [x1, y1],
930
+ },
931
+ });
932
+
933
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
934
+ });
935
+
936
+ cy.log("move copied second point");
937
+ cy.window().then(async (win) => {
938
+ x2 = -7;
939
+ y2 = -5;
940
+
941
+ win.callAction1({
942
+ actionName: "moveLineSegment",
943
+ componentName: "/g1/ls",
944
+ args: {
945
+ point2coords: [x2, y2],
946
+ },
947
+ });
948
+
949
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
950
+ });
951
+
952
+ cy.log("move copied first point");
953
+ cy.window().then(async (win) => {
954
+ x1 = 6;
955
+ y1 = 0;
956
+
957
+ win.callAction1({
958
+ actionName: "moveLineSegment",
959
+ componentName: "/g2/ls",
960
+ args: {
961
+ point1coords: [x1, y1],
962
+ },
963
+ });
964
+
965
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
966
+ });
967
+
968
+ cy.log("move copied second point");
969
+ cy.window().then(async (win) => {
970
+ x2 = 9;
971
+ y2 = -8;
972
+
973
+ win.callAction1({
974
+ actionName: "moveLineSegment",
975
+ componentName: "/g2/ls",
976
+ args: {
977
+ point2coords: [x2, y2],
978
+ },
979
+ });
980
+
981
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
982
+ });
983
+
984
+ cy.log("move double copied first point");
985
+ cy.window().then(async (win) => {
986
+ x1 = -5;
987
+ y1 = 7;
988
+
989
+ win.callAction1({
990
+ actionName: "moveLineSegment",
991
+ componentName: "/g3/ls",
992
+ args: {
993
+ point1coords: [x1, y1],
994
+ },
995
+ });
996
+
997
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
998
+ });
999
+
1000
+ cy.log("move double copied second point");
1001
+ cy.window().then(async (win) => {
1002
+ x2 = -1;
1003
+ y2 = 3;
1004
+
1005
+ win.callAction1({
1006
+ actionName: "moveLineSegment",
1007
+ componentName: "/g3/ls",
1008
+ args: {
1009
+ point2coords: [x2, y2],
1010
+ },
1011
+ });
1012
+
1013
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
1014
+ });
1015
+ });
1016
+
1017
+ it("lineSegment with multiple layers of copied points", () => {
1018
+ cy.window().then(async (win) => {
1019
+ win.postMessage(
1020
+ {
1021
+ doenetML: `
1022
+ <text>a</text>
1023
+ <point>(2,1)</point>
1024
+ <point>(-2,-5)</point>
1025
+ <copy target="_point1" />
1026
+ <copy target="_point2" />
1027
+ <copy target="_copy1" />
1028
+ <copy target="_copy2" />
1029
+ <copy target="_copy3" />
1030
+ <copy target="_copy4" />
1031
+
1032
+ <graph name="g1" newNamespace>
1033
+ <lineSegment endpoints="$(../_copy5) $(../_copy6)" name="ls"/>
1034
+ </graph>
1035
+
1036
+ <graph name="g2" newNamespace>
1037
+ <copy assignNames="ls" target="../g1/ls" />
1038
+ </graph>
1039
+
1040
+ <copy assignNames="g3" target="g2" />
1041
+
1042
+ <copy prop="endpoint1" target="g1/ls" assignNames="p1" />
1043
+ <copy prop="endpoint2" target="g1/ls" assignNames="p2" />
1044
+ `,
1045
+ },
1046
+ "*",
1047
+ );
1048
+ });
1049
+
1050
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
1051
+
1052
+ let x1 = 2,
1053
+ y1 = 1;
1054
+ let x2 = -2,
1055
+ y2 = -5;
1056
+
1057
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
1058
+
1059
+ cy.log("move original first point");
1060
+ cy.window().then(async (win) => {
1061
+ x1 = 3;
1062
+ y1 = -5;
1063
+
1064
+ win.callAction1({
1065
+ actionName: "moveLineSegment",
1066
+ componentName: "/g1/ls",
1067
+ args: {
1068
+ point1coords: [x1, y1],
1069
+ },
1070
+ });
1071
+
1072
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
1073
+ });
1074
+
1075
+ cy.log("move copied second point");
1076
+ cy.window().then(async (win) => {
1077
+ x2 = -7;
1078
+ y2 = -5;
1079
+
1080
+ win.callAction1({
1081
+ actionName: "moveLineSegment",
1082
+ componentName: "/g1/ls",
1083
+ args: {
1084
+ point2coords: [x2, y2],
1085
+ },
1086
+ });
1087
+
1088
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
1089
+ });
1090
+
1091
+ cy.log("move copied first point");
1092
+ cy.window().then(async (win) => {
1093
+ x1 = 6;
1094
+ y1 = 0;
1095
+
1096
+ win.callAction1({
1097
+ actionName: "moveLineSegment",
1098
+ componentName: "/g2/ls",
1099
+ args: {
1100
+ point1coords: [x1, y1],
1101
+ },
1102
+ });
1103
+
1104
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
1105
+ });
1106
+
1107
+ cy.log("move copied second point");
1108
+ cy.window().then(async (win) => {
1109
+ x2 = 9;
1110
+ y2 = -8;
1111
+
1112
+ win.callAction1({
1113
+ actionName: "moveLineSegment",
1114
+ componentName: "/g2/ls",
1115
+ args: {
1116
+ point2coords: [x2, y2],
1117
+ },
1118
+ });
1119
+
1120
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
1121
+ });
1122
+
1123
+ cy.log("move double copied first point");
1124
+ cy.window().then(async (win) => {
1125
+ x1 = -5;
1126
+ y1 = 7;
1127
+
1128
+ win.callAction1({
1129
+ actionName: "moveLineSegment",
1130
+ componentName: "/g3/ls",
1131
+ args: {
1132
+ point1coords: [x1, y1],
1133
+ },
1134
+ });
1135
+
1136
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
1137
+ });
1138
+
1139
+ cy.log("move double copied second point");
1140
+ cy.window().then(async (win) => {
1141
+ x2 = -1;
1142
+ y2 = 3;
1143
+
1144
+ win.callAction1({
1145
+ actionName: "moveLineSegment",
1146
+ componentName: "/g3/ls",
1147
+ args: {
1148
+ point2coords: [x2, y2],
1149
+ },
1150
+ });
1151
+
1152
+ testLineSegmentCopiedTwice({ x1, y1, x2, y2 });
1153
+ });
1154
+ });
1155
+
1156
+ it("initially non-numeric point", () => {
1157
+ cy.window().then(async (win) => {
1158
+ win.postMessage(
1159
+ {
1160
+ doenetML: `
1161
+ <text>a</text>
1162
+ <mathinput name="x" prefill="q"/>
1163
+ <graph>
1164
+ <lineSegment endpoints="($x,2) (-2,3)" />
1165
+ </graph>
1166
+ <copy prop="endpoint1" target="_linesegment1" assignNames="p1" />
1167
+ `,
1168
+ },
1169
+ "*",
1170
+ );
1171
+ });
1172
+
1173
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
1174
+
1175
+ cy.log("check initial values");
1176
+ cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", "(q,2)");
1177
+ cy.window().then(async (win) => {
1178
+ let stateVariables = await win.returnAllStateVariables1();
1179
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
1180
+ "q",
1181
+ 2,
1182
+ ]);
1183
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
1184
+ -2, 3,
1185
+ ]);
1186
+ });
1187
+
1188
+ cy.log("change point to be numeric");
1189
+ cy.get(cesc("#\\/x") + " textarea").type("{end}{backspace}5{enter}", {
1190
+ force: true,
1191
+ });
1192
+
1193
+ cy.get(cesc("#\\/p1") + " .mjx-mrow").should("contain.text", "(5,2)");
1194
+
1195
+ cy.window().then(async (win) => {
1196
+ let stateVariables = await win.returnAllStateVariables1();
1197
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
1198
+ 5, 2,
1199
+ ]);
1200
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
1201
+ -2, 3,
1202
+ ]);
1203
+ });
1204
+ });
1205
+
1206
+ it("linesegment with one endpoint, copy and overwrite the point", () => {
1207
+ cy.window().then(async (win) => {
1208
+ win.postMessage(
1209
+ {
1210
+ doenetML: `
1211
+ <text>a</text>
1212
+ <graph name="g1" newNamespace>
1213
+ <linesegment endpoints="(-5,9)" name="l" />
1214
+ <copy prop="endpoint1" target="l" assignNames="A" />
1215
+ <copy prop="endpoint2" target="l" assignNames="B" />
1216
+ </graph>
1217
+
1218
+ <graph newNamespace name="g2">
1219
+ <copy target="../g1/l" assignNames="l" endpoints="(4,-2)" />
1220
+ <copy prop="endpoint1" target="l" assignNames="A" />
1221
+ <copy prop="endpoint2" target="l" assignNames="B" />
1222
+ </graph>
1223
+
1224
+ <graph newNamespace name="g3">
1225
+ <copy target="../g2/l" assignNames="l" />
1226
+ <copy prop="endpoint1" target="l" assignNames="A" />
1227
+ <copy prop="endpoint2" target="l" assignNames="B" />
1228
+ </graph>
1229
+
1230
+ <graph newNamespace name="g4">
1231
+ <copy target="../g2/_copy1" assignNames="l" />
1232
+ <copy prop="endpoint1" target="l" assignNames="A" />
1233
+ <copy prop="endpoint2" target="l" assignNames="B" />
1234
+ </graph>
1235
+
1236
+ <copy target="g2" assignNames="g5" />
1237
+
1238
+ <copy prop="endpointX1_1" target="g1/l" assignNames="x11" />
1239
+ <copy prop="endpointX1_2" target="g1/l" assignNames="y11" />
1240
+ <copy prop="endpointX2_1" target="g1/l" assignNames="x2" />
1241
+ <copy prop="endpointX2_2" target="g1/l" assignNames="y2" />
1242
+ <copy prop="endpointX1_1" target="g2/l" assignNames="x12" />
1243
+ <copy prop="endpointX1_2" target="g2/l" assignNames="y12" />
1244
+
1245
+ `,
1246
+ },
1247
+ "*",
1248
+ );
1249
+ });
1250
+
1251
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
1252
+
1253
+ async function checkLineSegments({ x11, y11, x12, y12, x2, y2 }) {
1254
+ cy.get(cesc("#\\/x11") + " .mjx-mrow").should(
1255
+ "contain.text",
1256
+ `${nInDOM(x11).substring(0, 6)}`,
1257
+ );
1258
+ cy.get(cesc("#\\/y11") + " .mjx-mrow").should(
1259
+ "contain.text",
1260
+ `${nInDOM(y11).substring(0, 6)}`,
1261
+ );
1262
+ cy.get(cesc("#\\/x2") + " .mjx-mrow").should(
1263
+ "contain.text",
1264
+ `${nInDOM(x2).substring(0, 6)}`,
1265
+ );
1266
+ cy.get(cesc("#\\/y2") + " .mjx-mrow").should(
1267
+ "contain.text",
1268
+ `${nInDOM(y2).substring(0, 6)}`,
1269
+ );
1270
+ cy.get(cesc("#\\/x12") + " .mjx-mrow").should(
1271
+ "contain.text",
1272
+ `${nInDOM(x12).substring(0, 6)}`,
1273
+ );
1274
+ cy.get(cesc("#\\/y12") + " .mjx-mrow").should(
1275
+ "contain.text",
1276
+ `${nInDOM(y12).substring(0, 6)}`,
1277
+ );
1278
+
1279
+ cy.window().then(async (win) => {
1280
+ let stateVariables = await win.returnAllStateVariables1();
1281
+
1282
+ expect(
1283
+ me
1284
+ .fromAst(stateVariables["/g1/l"].stateValues.endpoints[0][0])
1285
+ .evaluate_to_constant(),
1286
+ ).closeTo(x11, 1e-12);
1287
+ expect(
1288
+ me
1289
+ .fromAst(stateVariables["/g1/l"].stateValues.endpoints[0][1])
1290
+ .evaluate_to_constant(),
1291
+ ).closeTo(y11, 1e-12);
1292
+ expect(
1293
+ me
1294
+ .fromAst(stateVariables["/g1/l"].stateValues.endpoints[1][0])
1295
+ .evaluate_to_constant(),
1296
+ ).closeTo(x2, 1e-12);
1297
+ expect(
1298
+ me
1299
+ .fromAst(stateVariables["/g1/l"].stateValues.endpoints[1][1])
1300
+ .evaluate_to_constant(),
1301
+ ).closeTo(y2, 1e-12);
1302
+
1303
+ expect(
1304
+ me
1305
+ .fromAst(stateVariables["/g2/l"].stateValues.endpoints[0][0])
1306
+ .evaluate_to_constant(),
1307
+ ).closeTo(x12, 1e-12);
1308
+ expect(
1309
+ me
1310
+ .fromAst(stateVariables["/g2/l"].stateValues.endpoints[0][1])
1311
+ .evaluate_to_constant(),
1312
+ ).closeTo(y12, 1e-12);
1313
+ expect(
1314
+ me
1315
+ .fromAst(stateVariables["/g2/l"].stateValues.endpoints[1][0])
1316
+ .evaluate_to_constant(),
1317
+ ).closeTo(x2, 1e-12);
1318
+ expect(
1319
+ me
1320
+ .fromAst(stateVariables["/g2/l"].stateValues.endpoints[1][1])
1321
+ .evaluate_to_constant(),
1322
+ ).closeTo(y2, 1e-12);
1323
+
1324
+ expect(
1325
+ me
1326
+ .fromAst(stateVariables["/g3/l"].stateValues.endpoints[0][0])
1327
+ .evaluate_to_constant(),
1328
+ ).closeTo(x12, 1e-12);
1329
+ expect(
1330
+ me
1331
+ .fromAst(stateVariables["/g3/l"].stateValues.endpoints[0][1])
1332
+ .evaluate_to_constant(),
1333
+ ).closeTo(y12, 1e-12);
1334
+ expect(
1335
+ me
1336
+ .fromAst(stateVariables["/g3/l"].stateValues.endpoints[1][0])
1337
+ .evaluate_to_constant(),
1338
+ ).closeTo(x2, 1e-12);
1339
+ expect(
1340
+ me
1341
+ .fromAst(stateVariables["/g3/l"].stateValues.endpoints[1][1])
1342
+ .evaluate_to_constant(),
1343
+ ).closeTo(y2, 1e-12);
1344
+
1345
+ expect(
1346
+ me
1347
+ .fromAst(stateVariables["/g4/l"].stateValues.endpoints[0][0])
1348
+ .evaluate_to_constant(),
1349
+ ).closeTo(x12, 1e-12);
1350
+ expect(
1351
+ me
1352
+ .fromAst(stateVariables["/g4/l"].stateValues.endpoints[0][1])
1353
+ .evaluate_to_constant(),
1354
+ ).closeTo(y12, 1e-12);
1355
+ expect(
1356
+ me
1357
+ .fromAst(stateVariables["/g4/l"].stateValues.endpoints[1][0])
1358
+ .evaluate_to_constant(),
1359
+ ).closeTo(x2, 1e-12);
1360
+ expect(
1361
+ me
1362
+ .fromAst(stateVariables["/g4/l"].stateValues.endpoints[1][1])
1363
+ .evaluate_to_constant(),
1364
+ ).closeTo(y2, 1e-12);
1365
+
1366
+ expect(
1367
+ me
1368
+ .fromAst(stateVariables["/g5/l"].stateValues.endpoints[0][0])
1369
+ .evaluate_to_constant(),
1370
+ ).closeTo(x12, 1e-12);
1371
+ expect(
1372
+ me
1373
+ .fromAst(stateVariables["/g5/l"].stateValues.endpoints[0][1])
1374
+ .evaluate_to_constant(),
1375
+ ).closeTo(y12, 1e-12);
1376
+ expect(
1377
+ me
1378
+ .fromAst(stateVariables["/g5/l"].stateValues.endpoints[1][0])
1379
+ .evaluate_to_constant(),
1380
+ ).closeTo(x2, 1e-12);
1381
+ expect(
1382
+ me
1383
+ .fromAst(stateVariables["/g5/l"].stateValues.endpoints[1][1])
1384
+ .evaluate_to_constant(),
1385
+ ).closeTo(y2, 1e-12);
1386
+
1387
+ expect(stateVariables["/g1/A"].stateValues.xs[0]).closeTo(x11, 1e-12);
1388
+ expect(stateVariables["/g1/A"].stateValues.xs[1]).closeTo(y11, 1e-12);
1389
+ expect(stateVariables["/g1/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1390
+ expect(stateVariables["/g1/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1391
+
1392
+ expect(stateVariables["/g2/A"].stateValues.xs[0]).closeTo(x12, 1e-12);
1393
+ expect(stateVariables["/g2/A"].stateValues.xs[1]).closeTo(y12, 1e-12);
1394
+ expect(stateVariables["/g2/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1395
+ expect(stateVariables["/g2/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1396
+
1397
+ expect(stateVariables["/g3/A"].stateValues.xs[0]).closeTo(x12, 1e-12);
1398
+ expect(stateVariables["/g3/A"].stateValues.xs[1]).closeTo(y12, 1e-12);
1399
+ expect(stateVariables["/g3/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1400
+ expect(stateVariables["/g3/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1401
+
1402
+ expect(stateVariables["/g4/A"].stateValues.xs[0]).closeTo(x12, 1e-12);
1403
+ expect(stateVariables["/g4/A"].stateValues.xs[1]).closeTo(y12, 1e-12);
1404
+ expect(stateVariables["/g4/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1405
+ expect(stateVariables["/g4/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1406
+
1407
+ expect(stateVariables["/g5/A"].stateValues.xs[0]).closeTo(x12, 1e-12);
1408
+ expect(stateVariables["/g5/A"].stateValues.xs[1]).closeTo(y12, 1e-12);
1409
+ expect(stateVariables["/g5/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1410
+ expect(stateVariables["/g5/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1411
+ });
1412
+ }
1413
+
1414
+ let x11 = -5,
1415
+ y11 = 9;
1416
+ let x12 = 4,
1417
+ y12 = -2;
1418
+ let x2 = 0,
1419
+ y2 = 0;
1420
+
1421
+ cy.window().then(async (win) => {
1422
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1423
+ });
1424
+
1425
+ cy.log("move point g1/A");
1426
+ cy.window().then(async (win) => {
1427
+ x11 = 7;
1428
+ y11 = -3;
1429
+ win.callAction1({
1430
+ actionName: "movePoint",
1431
+ componentName: "/g1/A",
1432
+ args: { x: x11, y: y11 },
1433
+ });
1434
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1435
+ });
1436
+
1437
+ cy.log("move point g1/B");
1438
+ cy.window().then(async (win) => {
1439
+ x2 = -1;
1440
+ y2 = -4;
1441
+ win.callAction1({
1442
+ actionName: "movePoint",
1443
+ componentName: "/g1/B",
1444
+ args: { x: x2, y: y2 },
1445
+ });
1446
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1447
+ });
1448
+
1449
+ cy.log("move line g1/l");
1450
+ cy.window().then(async (win) => {
1451
+ x11 = 5;
1452
+ y11 = 3;
1453
+ x2 = -7;
1454
+ y2 = -8;
1455
+ win.callAction1({
1456
+ actionName: "moveLineSegment",
1457
+ componentName: "/g1/l",
1458
+ args: {
1459
+ point1coords: [x11, y11],
1460
+ point2coords: [x2, y2],
1461
+ },
1462
+ });
1463
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1464
+ });
1465
+
1466
+ cy.log("move point g2/A");
1467
+ cy.window().then(async (win) => {
1468
+ x12 = -1;
1469
+ y12 = 0;
1470
+ win.callAction1({
1471
+ actionName: "movePoint",
1472
+ componentName: "/g2/A",
1473
+ args: { x: x12, y: y12 },
1474
+ });
1475
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1476
+ });
1477
+
1478
+ cy.log("move point g2/B");
1479
+ cy.window().then(async (win) => {
1480
+ x2 = 6;
1481
+ y2 = -6;
1482
+ win.callAction1({
1483
+ actionName: "movePoint",
1484
+ componentName: "/g2/B",
1485
+ args: { x: x2, y: y2 },
1486
+ });
1487
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1488
+ });
1489
+
1490
+ cy.log("move line g2/l");
1491
+ cy.window().then(async (win) => {
1492
+ x12 = 10;
1493
+ y12 = 9;
1494
+ x2 = 8;
1495
+ y2 = 7;
1496
+ win.callAction1({
1497
+ actionName: "moveLineSegment",
1498
+ componentName: "/g2/l",
1499
+ args: {
1500
+ point1coords: [x12, y12],
1501
+ point2coords: [x2, y2],
1502
+ },
1503
+ });
1504
+
1505
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1506
+ });
1507
+
1508
+ cy.log("move point g3/A");
1509
+ cy.window().then(async (win) => {
1510
+ x12 = -3;
1511
+ y12 = 7;
1512
+ win.callAction1({
1513
+ actionName: "movePoint",
1514
+ componentName: "/g3/A",
1515
+ args: { x: x12, y: y12 },
1516
+ });
1517
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1518
+ });
1519
+
1520
+ cy.log("move point g3/B");
1521
+ cy.window().then(async (win) => {
1522
+ x2 = -8;
1523
+ y2 = -4;
1524
+ win.callAction1({
1525
+ actionName: "movePoint",
1526
+ componentName: "/g3/B",
1527
+ args: { x: x2, y: y2 },
1528
+ });
1529
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1530
+ });
1531
+
1532
+ cy.log("move line g3/l");
1533
+ cy.window().then(async (win) => {
1534
+ x12 = 0;
1535
+ y12 = -1;
1536
+ x2 = 2;
1537
+ y2 = -3;
1538
+ win.callAction1({
1539
+ actionName: "moveLineSegment",
1540
+ componentName: "/g3/l",
1541
+ args: {
1542
+ point1coords: [x12, y12],
1543
+ point2coords: [x2, y2],
1544
+ },
1545
+ });
1546
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1547
+ });
1548
+
1549
+ cy.log("move point g4/A");
1550
+ cy.window().then(async (win) => {
1551
+ x12 = 9;
1552
+ y12 = 8;
1553
+ win.callAction1({
1554
+ actionName: "movePoint",
1555
+ componentName: "/g4/A",
1556
+ args: { x: x12, y: y12 },
1557
+ });
1558
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1559
+ });
1560
+
1561
+ cy.log("move point g4/B");
1562
+ cy.window().then(async (win) => {
1563
+ x2 = 6;
1564
+ y2 = -9;
1565
+ win.callAction1({
1566
+ actionName: "movePoint",
1567
+ componentName: "/g4/B",
1568
+ args: { x: x2, y: y2 },
1569
+ });
1570
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1571
+ });
1572
+
1573
+ cy.log("move line g4/l");
1574
+ cy.window().then(async (win) => {
1575
+ x12 = -3;
1576
+ y12 = 4;
1577
+ x2 = -5;
1578
+ y2 = 6;
1579
+ win.callAction1({
1580
+ actionName: "moveLineSegment",
1581
+ componentName: "/g4/l",
1582
+ args: {
1583
+ point1coords: [x12, y12],
1584
+ point2coords: [x2, y2],
1585
+ },
1586
+ });
1587
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1588
+ });
1589
+
1590
+ cy.log("move point g5/A");
1591
+ cy.window().then(async (win) => {
1592
+ x12 = 1;
1593
+ y12 = -3;
1594
+ win.callAction1({
1595
+ actionName: "movePoint",
1596
+ componentName: "/g5/A",
1597
+ args: { x: x12, y: y12 },
1598
+ });
1599
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1600
+ });
1601
+
1602
+ cy.log("move point g5/B");
1603
+ cy.window().then(async (win) => {
1604
+ x2 = 0;
1605
+ y2 = 7;
1606
+ win.callAction1({
1607
+ actionName: "movePoint",
1608
+ componentName: "/g5/B",
1609
+ args: { x: x2, y: y2 },
1610
+ });
1611
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1612
+ });
1613
+
1614
+ cy.log("move line g5/l");
1615
+ cy.window().then(async (win) => {
1616
+ let stateVariables = await win.returnAllStateVariables1();
1617
+
1618
+ x12 = 4;
1619
+ y12 = 5;
1620
+ x2 = -6;
1621
+ y2 = -7;
1622
+ win.callAction1({
1623
+ actionName: "moveLineSegment",
1624
+ componentName: "/g5/l",
1625
+ args: {
1626
+ point1coords: [x12, y12],
1627
+ point2coords: [x2, y2],
1628
+ },
1629
+ });
1630
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1631
+ });
1632
+ });
1633
+
1634
+ it("linesegment with one endpoint, copy and overwrite the point, swap linesegment", () => {
1635
+ cy.window().then(async (win) => {
1636
+ win.postMessage(
1637
+ {
1638
+ doenetML: `
1639
+ <text>a</text>
1640
+ <booleaninput name="b" />
1641
+ <graph name="g1" newNamespace>
1642
+ <conditionalContent assignNames="(l)">
1643
+ <case condition="$(../b)" >
1644
+ <linesegment endpoints="(1,2)" />
1645
+ </case>
1646
+ <else>
1647
+ <linesegment endpoints="(-5,9)" />
1648
+ </else>
1649
+ </conditionalContent>
1650
+ <copy prop="endpoint1" target="l" assignNames="A" />
1651
+ <copy prop="endpoint2" target="l" assignNames="B" />
1652
+ </graph>
1653
+
1654
+ <graph newNamespace name="g2">
1655
+ <copy target="../g1/l" assignNames="l" endpoints="(4,-2)" />
1656
+ <copy prop="endpoint1" target="l" assignNames="A" />
1657
+ <copy prop="endpoint2" target="l" assignNames="B" />
1658
+ </graph>
1659
+
1660
+ <graph newNamespace name="g3">
1661
+ <copy target="../g2/l" assignNames="l" />
1662
+ <copy prop="endpoint1" target="l" assignNames="A" />
1663
+ <copy prop="endpoint2" target="l" assignNames="B" />
1664
+ </graph>
1665
+
1666
+ <graph newNamespace name="g4">
1667
+ <copy target="../g2/_copy1" assignNames="l" />
1668
+ <copy prop="endpoint1" target="l" assignNames="A" />
1669
+ <copy prop="endpoint2" target="l" assignNames="B" />
1670
+ </graph>
1671
+
1672
+ <copy target="g2" assignNames="g5" />
1673
+
1674
+ <copy prop="endpointX1_1" target="g1/l" assignNames="x11" />
1675
+ <copy prop="endpointX1_2" target="g1/l" assignNames="y11" />
1676
+ <copy prop="endpointX2_1" target="g1/l" assignNames="x2" />
1677
+ <copy prop="endpointX2_2" target="g1/l" assignNames="y2" />
1678
+ <copy prop="endpointX1_1" target="g2/l" assignNames="x12" />
1679
+ <copy prop="endpointX1_2" target="g2/l" assignNames="y12" />
1680
+
1681
+ `,
1682
+ },
1683
+ "*",
1684
+ );
1685
+ });
1686
+
1687
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
1688
+
1689
+ async function checkLineSegments({ x11, y11, x12, y12, x2, y2 }) {
1690
+ cy.get(cesc("#\\/x11") + " .mjx-mrow").should(
1691
+ "contain.text",
1692
+ `${nInDOM(x11).substring(0, 6)}`,
1693
+ );
1694
+ cy.get(cesc("#\\/y11") + " .mjx-mrow").should(
1695
+ "contain.text",
1696
+ `${nInDOM(y11).substring(0, 6)}`,
1697
+ );
1698
+ cy.get(cesc("#\\/x2") + " .mjx-mrow").should(
1699
+ "contain.text",
1700
+ `${nInDOM(x2).substring(0, 6)}`,
1701
+ );
1702
+ cy.get(cesc("#\\/y2") + " .mjx-mrow").should(
1703
+ "contain.text",
1704
+ `${nInDOM(y2).substring(0, 6)}`,
1705
+ );
1706
+ cy.get(cesc("#\\/x12") + " .mjx-mrow").should(
1707
+ "contain.text",
1708
+ `${nInDOM(x12).substring(0, 6)}`,
1709
+ );
1710
+ cy.get(cesc("#\\/y12") + " .mjx-mrow").should(
1711
+ "contain.text",
1712
+ `${nInDOM(y12).substring(0, 6)}`,
1713
+ );
1714
+
1715
+ cy.window().then(async (win) => {
1716
+ let stateVariables = await win.returnAllStateVariables1();
1717
+
1718
+ expect(
1719
+ me
1720
+ .fromAst(stateVariables["/g1/l"].stateValues.endpoints[0][0])
1721
+ .evaluate_to_constant(),
1722
+ ).closeTo(x11, 1e-12);
1723
+ expect(
1724
+ me
1725
+ .fromAst(stateVariables["/g1/l"].stateValues.endpoints[0][1])
1726
+ .evaluate_to_constant(),
1727
+ ).closeTo(y11, 1e-12);
1728
+ expect(
1729
+ me
1730
+ .fromAst(stateVariables["/g1/l"].stateValues.endpoints[1][0])
1731
+ .evaluate_to_constant(),
1732
+ ).closeTo(x2, 1e-12);
1733
+ expect(
1734
+ me
1735
+ .fromAst(stateVariables["/g1/l"].stateValues.endpoints[1][1])
1736
+ .evaluate_to_constant(),
1737
+ ).closeTo(y2, 1e-12);
1738
+
1739
+ expect(
1740
+ me
1741
+ .fromAst(stateVariables["/g2/l"].stateValues.endpoints[0][0])
1742
+ .evaluate_to_constant(),
1743
+ ).closeTo(x12, 1e-12);
1744
+ expect(
1745
+ me
1746
+ .fromAst(stateVariables["/g2/l"].stateValues.endpoints[0][1])
1747
+ .evaluate_to_constant(),
1748
+ ).closeTo(y12, 1e-12);
1749
+ expect(
1750
+ me
1751
+ .fromAst(stateVariables["/g2/l"].stateValues.endpoints[1][0])
1752
+ .evaluate_to_constant(),
1753
+ ).closeTo(x2, 1e-12);
1754
+ expect(
1755
+ me
1756
+ .fromAst(stateVariables["/g2/l"].stateValues.endpoints[1][1])
1757
+ .evaluate_to_constant(),
1758
+ ).closeTo(y2, 1e-12);
1759
+
1760
+ expect(
1761
+ me
1762
+ .fromAst(stateVariables["/g3/l"].stateValues.endpoints[0][0])
1763
+ .evaluate_to_constant(),
1764
+ ).closeTo(x12, 1e-12);
1765
+ expect(
1766
+ me
1767
+ .fromAst(stateVariables["/g3/l"].stateValues.endpoints[0][1])
1768
+ .evaluate_to_constant(),
1769
+ ).closeTo(y12, 1e-12);
1770
+ expect(
1771
+ me
1772
+ .fromAst(stateVariables["/g3/l"].stateValues.endpoints[1][0])
1773
+ .evaluate_to_constant(),
1774
+ ).closeTo(x2, 1e-12);
1775
+ expect(
1776
+ me
1777
+ .fromAst(stateVariables["/g3/l"].stateValues.endpoints[1][1])
1778
+ .evaluate_to_constant(),
1779
+ ).closeTo(y2, 1e-12);
1780
+
1781
+ expect(
1782
+ me
1783
+ .fromAst(stateVariables["/g4/l"].stateValues.endpoints[0][0])
1784
+ .evaluate_to_constant(),
1785
+ ).closeTo(x12, 1e-12);
1786
+ expect(
1787
+ me
1788
+ .fromAst(stateVariables["/g4/l"].stateValues.endpoints[0][1])
1789
+ .evaluate_to_constant(),
1790
+ ).closeTo(y12, 1e-12);
1791
+ expect(
1792
+ me
1793
+ .fromAst(stateVariables["/g4/l"].stateValues.endpoints[1][0])
1794
+ .evaluate_to_constant(),
1795
+ ).closeTo(x2, 1e-12);
1796
+ expect(
1797
+ me
1798
+ .fromAst(stateVariables["/g4/l"].stateValues.endpoints[1][1])
1799
+ .evaluate_to_constant(),
1800
+ ).closeTo(y2, 1e-12);
1801
+
1802
+ expect(
1803
+ me
1804
+ .fromAst(stateVariables["/g5/l"].stateValues.endpoints[0][0])
1805
+ .evaluate_to_constant(),
1806
+ ).closeTo(x12, 1e-12);
1807
+ expect(
1808
+ me
1809
+ .fromAst(stateVariables["/g5/l"].stateValues.endpoints[0][1])
1810
+ .evaluate_to_constant(),
1811
+ ).closeTo(y12, 1e-12);
1812
+ expect(
1813
+ me
1814
+ .fromAst(stateVariables["/g5/l"].stateValues.endpoints[1][0])
1815
+ .evaluate_to_constant(),
1816
+ ).closeTo(x2, 1e-12);
1817
+ expect(
1818
+ me
1819
+ .fromAst(stateVariables["/g5/l"].stateValues.endpoints[1][1])
1820
+ .evaluate_to_constant(),
1821
+ ).closeTo(y2, 1e-12);
1822
+
1823
+ expect(stateVariables["/g1/A"].stateValues.xs[0]).closeTo(x11, 1e-12);
1824
+ expect(stateVariables["/g1/A"].stateValues.xs[1]).closeTo(y11, 1e-12);
1825
+ expect(stateVariables["/g1/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1826
+ expect(stateVariables["/g1/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1827
+
1828
+ expect(stateVariables["/g2/A"].stateValues.xs[0]).closeTo(x12, 1e-12);
1829
+ expect(stateVariables["/g2/A"].stateValues.xs[1]).closeTo(y12, 1e-12);
1830
+ expect(stateVariables["/g2/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1831
+ expect(stateVariables["/g2/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1832
+
1833
+ expect(stateVariables["/g3/A"].stateValues.xs[0]).closeTo(x12, 1e-12);
1834
+ expect(stateVariables["/g3/A"].stateValues.xs[1]).closeTo(y12, 1e-12);
1835
+ expect(stateVariables["/g3/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1836
+ expect(stateVariables["/g3/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1837
+
1838
+ expect(stateVariables["/g4/A"].stateValues.xs[0]).closeTo(x12, 1e-12);
1839
+ expect(stateVariables["/g4/A"].stateValues.xs[1]).closeTo(y12, 1e-12);
1840
+ expect(stateVariables["/g4/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1841
+ expect(stateVariables["/g4/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1842
+
1843
+ expect(stateVariables["/g5/A"].stateValues.xs[0]).closeTo(x12, 1e-12);
1844
+ expect(stateVariables["/g5/A"].stateValues.xs[1]).closeTo(y12, 1e-12);
1845
+ expect(stateVariables["/g5/B"].stateValues.xs[0]).closeTo(x2, 1e-12);
1846
+ expect(stateVariables["/g5/B"].stateValues.xs[1]).closeTo(y2, 1e-12);
1847
+ });
1848
+ }
1849
+
1850
+ let x11 = -5,
1851
+ y11 = 9;
1852
+ let x12 = 4,
1853
+ y12 = -2;
1854
+ let x2 = 0,
1855
+ y2 = 0;
1856
+
1857
+ cy.window().then(async (win) => {
1858
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1859
+ });
1860
+
1861
+ cy.log("move point g1/A");
1862
+ cy.window().then(async (win) => {
1863
+ x11 = 7;
1864
+ y11 = -3;
1865
+ win.callAction1({
1866
+ actionName: "movePoint",
1867
+ componentName: "/g1/A",
1868
+ args: { x: x11, y: y11 },
1869
+ });
1870
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1871
+ });
1872
+
1873
+ cy.log("move point g1/B");
1874
+ cy.window().then(async (win) => {
1875
+ x2 = -1;
1876
+ y2 = -4;
1877
+ win.callAction1({
1878
+ actionName: "movePoint",
1879
+ componentName: "/g1/B",
1880
+ args: { x: x2, y: y2 },
1881
+ });
1882
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1883
+ });
1884
+
1885
+ cy.log("move line g1/l");
1886
+ cy.window().then(async (win) => {
1887
+ x11 = 5;
1888
+ y11 = 3;
1889
+ x2 = -7;
1890
+ y2 = -8;
1891
+ win.callAction1({
1892
+ actionName: "moveLineSegment",
1893
+ componentName: "/g1/l",
1894
+ args: {
1895
+ point1coords: [x11, y11],
1896
+ point2coords: [x2, y2],
1897
+ },
1898
+ });
1899
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1900
+ });
1901
+
1902
+ cy.log("move point g2/A");
1903
+ cy.window().then(async (win) => {
1904
+ x12 = -1;
1905
+ y12 = 0;
1906
+ win.callAction1({
1907
+ actionName: "movePoint",
1908
+ componentName: "/g2/A",
1909
+ args: { x: x12, y: y12 },
1910
+ });
1911
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1912
+ });
1913
+
1914
+ cy.log("move point g2/B");
1915
+ cy.window().then(async (win) => {
1916
+ x2 = 6;
1917
+ y2 = -6;
1918
+ win.callAction1({
1919
+ actionName: "movePoint",
1920
+ componentName: "/g2/B",
1921
+ args: { x: x2, y: y2 },
1922
+ });
1923
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1924
+ });
1925
+
1926
+ cy.log("move line g2/l");
1927
+ cy.window().then(async (win) => {
1928
+ x12 = 10;
1929
+ y12 = 9;
1930
+ x2 = 8;
1931
+ y2 = 7;
1932
+ win.callAction1({
1933
+ actionName: "moveLineSegment",
1934
+ componentName: "/g2/l",
1935
+ args: {
1936
+ point1coords: [x12, y12],
1937
+ point2coords: [x2, y2],
1938
+ },
1939
+ });
1940
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1941
+ });
1942
+
1943
+ cy.log("move point g3/A");
1944
+ cy.window().then(async (win) => {
1945
+ x12 = -3;
1946
+ y12 = 7;
1947
+ win.callAction1({
1948
+ actionName: "movePoint",
1949
+ componentName: "/g3/A",
1950
+ args: { x: x12, y: y12 },
1951
+ });
1952
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1953
+ });
1954
+
1955
+ cy.log("move point g3/B");
1956
+ cy.window().then(async (win) => {
1957
+ x2 = -8;
1958
+ y2 = -4;
1959
+ win.callAction1({
1960
+ actionName: "movePoint",
1961
+ componentName: "/g3/B",
1962
+ args: { x: x2, y: y2 },
1963
+ });
1964
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1965
+ });
1966
+
1967
+ cy.log("move line g3/l");
1968
+ cy.window().then(async (win) => {
1969
+ x12 = 0;
1970
+ y12 = -1;
1971
+ x2 = 2;
1972
+ y2 = -3;
1973
+ win.callAction1({
1974
+ actionName: "moveLineSegment",
1975
+ componentName: "/g3/l",
1976
+ args: {
1977
+ point1coords: [x12, y12],
1978
+ point2coords: [x2, y2],
1979
+ },
1980
+ });
1981
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1982
+ });
1983
+
1984
+ cy.log("move point g4/A");
1985
+ cy.window().then(async (win) => {
1986
+ x12 = 9;
1987
+ y12 = 8;
1988
+ win.callAction1({
1989
+ actionName: "movePoint",
1990
+ componentName: "/g4/A",
1991
+ args: { x: x12, y: y12 },
1992
+ });
1993
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
1994
+ });
1995
+
1996
+ cy.log("move point g4/B");
1997
+ cy.window().then(async (win) => {
1998
+ x2 = 6;
1999
+ y2 = -9;
2000
+ win.callAction1({
2001
+ actionName: "movePoint",
2002
+ componentName: "/g4/B",
2003
+ args: { x: x2, y: y2 },
2004
+ });
2005
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2006
+ });
2007
+
2008
+ cy.log("move line g4/l");
2009
+ cy.window().then(async (win) => {
2010
+ x12 = -3;
2011
+ y12 = 4;
2012
+ x2 = -5;
2013
+ y2 = 6;
2014
+ win.callAction1({
2015
+ actionName: "moveLineSegment",
2016
+ componentName: "/g4/l",
2017
+ args: {
2018
+ point1coords: [x12, y12],
2019
+ point2coords: [x2, y2],
2020
+ },
2021
+ });
2022
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2023
+ });
2024
+
2025
+ cy.log("move point g5/A");
2026
+ cy.window().then(async (win) => {
2027
+ x12 = 1;
2028
+ y12 = -3;
2029
+ win.callAction1({
2030
+ actionName: "movePoint",
2031
+ componentName: "/g5/A",
2032
+ args: { x: x12, y: y12 },
2033
+ });
2034
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2035
+ });
2036
+
2037
+ cy.log("move point g5/B");
2038
+ cy.window().then(async (win) => {
2039
+ x2 = 0;
2040
+ y2 = 7;
2041
+ win.callAction1({
2042
+ actionName: "movePoint",
2043
+ componentName: "/g5/B",
2044
+ args: { x: x2, y: y2 },
2045
+ });
2046
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2047
+ });
2048
+
2049
+ cy.log("move line g5/l");
2050
+ cy.window().then(async (win) => {
2051
+ x12 = 4;
2052
+ y12 = 5;
2053
+ x2 = -6;
2054
+ y2 = -7;
2055
+ win.callAction1({
2056
+ actionName: "moveLineSegment",
2057
+ componentName: "/g5/l",
2058
+ args: {
2059
+ point1coords: [x12, y12],
2060
+ point2coords: [x2, y2],
2061
+ },
2062
+ });
2063
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2064
+ });
2065
+
2066
+ cy.get(cesc("#\\/b_input")).check({ force: true });
2067
+
2068
+ cy.window().then(async (win) => {
2069
+ (x11 = 1), (y11 = 2);
2070
+ (x12 = 4), (y12 = -2);
2071
+ (x2 = 0), (y2 = 0);
2072
+
2073
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2074
+ });
2075
+
2076
+ cy.log("move point g1/A");
2077
+ cy.window().then(async (win) => {
2078
+ x11 = 7;
2079
+ y11 = -3;
2080
+ win.callAction1({
2081
+ actionName: "movePoint",
2082
+ componentName: "/g1/A",
2083
+ args: { x: x11, y: y11 },
2084
+ });
2085
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2086
+ });
2087
+
2088
+ cy.log("move point g1/B");
2089
+ cy.window().then(async (win) => {
2090
+ x2 = -1;
2091
+ y2 = -4;
2092
+ win.callAction1({
2093
+ actionName: "movePoint",
2094
+ componentName: "/g1/B",
2095
+ args: { x: x2, y: y2 },
2096
+ });
2097
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2098
+ });
2099
+
2100
+ cy.log("move line g1/l");
2101
+ cy.window().then(async (win) => {
2102
+ x11 = 5;
2103
+ y11 = 3;
2104
+ x2 = -7;
2105
+ y2 = -8;
2106
+ win.callAction1({
2107
+ actionName: "moveLineSegment",
2108
+ componentName: "/g1/l",
2109
+ args: {
2110
+ point1coords: [x11, y11],
2111
+ point2coords: [x2, y2],
2112
+ },
2113
+ });
2114
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2115
+ });
2116
+
2117
+ cy.log("move point g2/A");
2118
+ cy.window().then(async (win) => {
2119
+ x12 = -1;
2120
+ y12 = 0;
2121
+ win.callAction1({
2122
+ actionName: "movePoint",
2123
+ componentName: "/g2/A",
2124
+ args: { x: x12, y: y12 },
2125
+ });
2126
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2127
+ });
2128
+
2129
+ cy.log("move point g2/B");
2130
+ cy.window().then(async (win) => {
2131
+ x2 = 6;
2132
+ y2 = -6;
2133
+ win.callAction1({
2134
+ actionName: "movePoint",
2135
+ componentName: "/g2/B",
2136
+ args: { x: x2, y: y2 },
2137
+ });
2138
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2139
+ });
2140
+
2141
+ cy.log("move line g2/l");
2142
+ cy.window().then(async (win) => {
2143
+ x12 = 10;
2144
+ y12 = 9;
2145
+ x2 = 8;
2146
+ y2 = 7;
2147
+ win.callAction1({
2148
+ actionName: "moveLineSegment",
2149
+ componentName: "/g2/l",
2150
+ args: {
2151
+ point1coords: [x12, y12],
2152
+ point2coords: [x2, y2],
2153
+ },
2154
+ });
2155
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2156
+ });
2157
+
2158
+ cy.log("move point g3/A");
2159
+ cy.window().then(async (win) => {
2160
+ x12 = -3;
2161
+ y12 = 7;
2162
+ win.callAction1({
2163
+ actionName: "movePoint",
2164
+ componentName: "/g3/A",
2165
+ args: { x: x12, y: y12 },
2166
+ });
2167
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2168
+ });
2169
+
2170
+ cy.log("move point g3/B");
2171
+ cy.window().then(async (win) => {
2172
+ x2 = -8;
2173
+ y2 = -4;
2174
+ win.callAction1({
2175
+ actionName: "movePoint",
2176
+ componentName: "/g3/B",
2177
+ args: { x: x2, y: y2 },
2178
+ });
2179
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2180
+ });
2181
+
2182
+ cy.log("move line g3/l");
2183
+ cy.window().then(async (win) => {
2184
+ x12 = 0;
2185
+ y12 = -1;
2186
+ x2 = 2;
2187
+ y2 = -3;
2188
+ win.callAction1({
2189
+ actionName: "moveLineSegment",
2190
+ componentName: "/g3/l",
2191
+ args: {
2192
+ point1coords: [x12, y12],
2193
+ point2coords: [x2, y2],
2194
+ },
2195
+ });
2196
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2197
+ });
2198
+
2199
+ cy.log("move point g4/A");
2200
+ cy.window().then(async (win) => {
2201
+ x12 = 9;
2202
+ y12 = 8;
2203
+ win.callAction1({
2204
+ actionName: "movePoint",
2205
+ componentName: "/g4/A",
2206
+ args: { x: x12, y: y12 },
2207
+ });
2208
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2209
+ });
2210
+
2211
+ cy.log("move point g4/B");
2212
+ cy.window().then(async (win) => {
2213
+ x2 = 6;
2214
+ y2 = -9;
2215
+ win.callAction1({
2216
+ actionName: "movePoint",
2217
+ componentName: "/g4/B",
2218
+ args: { x: x2, y: y2 },
2219
+ });
2220
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2221
+ });
2222
+
2223
+ cy.log("move line g4/l");
2224
+ cy.window().then(async (win) => {
2225
+ x12 = -3;
2226
+ y12 = 4;
2227
+ x2 = -5;
2228
+ y2 = 6;
2229
+ win.callAction1({
2230
+ actionName: "moveLineSegment",
2231
+ componentName: "/g4/l",
2232
+ args: {
2233
+ point1coords: [x12, y12],
2234
+ point2coords: [x2, y2],
2235
+ },
2236
+ });
2237
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2238
+ });
2239
+
2240
+ cy.log("move point g5/A");
2241
+ cy.window().then(async (win) => {
2242
+ x12 = 1;
2243
+ y12 = -3;
2244
+ win.callAction1({
2245
+ actionName: "movePoint",
2246
+ componentName: "/g5/A",
2247
+ args: { x: x12, y: y12 },
2248
+ });
2249
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2250
+ });
2251
+
2252
+ cy.log("move point g5/B");
2253
+ cy.window().then(async (win) => {
2254
+ x2 = 0;
2255
+ y2 = 7;
2256
+ win.callAction1({
2257
+ actionName: "movePoint",
2258
+ componentName: "/g5/B",
2259
+ args: { x: x2, y: y2 },
2260
+ });
2261
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2262
+ });
2263
+
2264
+ cy.log("move line g5/l");
2265
+ cy.window().then(async (win) => {
2266
+ x12 = 4;
2267
+ y12 = 5;
2268
+ x2 = -6;
2269
+ y2 = -7;
2270
+ win.callAction1({
2271
+ actionName: "moveLineSegment",
2272
+ componentName: "/g5/l",
2273
+ args: {
2274
+ point1coords: [x12, y12],
2275
+ point2coords: [x2, y2],
2276
+ },
2277
+ });
2278
+ await checkLineSegments({ x11, y11, x12, y12, x2, y2 });
2279
+ });
2280
+ });
2281
+
2282
+ it("constrain to linesegment", () => {
2283
+ cy.window().then(async (win) => {
2284
+ win.postMessage(
2285
+ {
2286
+ doenetML: `
2287
+ <text>a</text>
2288
+ <graph>
2289
+ <point>(1,2)</point>
2290
+ <point>(3,4)</point>
2291
+ <linesegment endpoints="$_point1 $_point2" />
2292
+
2293
+ <point x="-5" y="2">
2294
+ <constraints>
2295
+ <constrainTo><copy target="_linesegment1" /></constrainTo>
2296
+ </constraints>
2297
+ </point>
2298
+ </graph>
2299
+ <copy target="_linesegment1" prop="endpoint1" assignNames="ep1a" />
2300
+ <copy target="_point3" assignNames="p3a" />
2301
+ `,
2302
+ },
2303
+ "*",
2304
+ );
2305
+ });
2306
+
2307
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
2308
+
2309
+ cy.log("check initial values");
2310
+
2311
+ cy.get(cesc("#\\/ep1a") + " .mjx-mrow").should(
2312
+ "contain.text",
2313
+ `(${nInDOM(1)},${nInDOM(2)})`,
2314
+ );
2315
+
2316
+ cy.window().then(async (win) => {
2317
+ let stateVariables = await win.returnAllStateVariables1();
2318
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
2319
+ 1, 2,
2320
+ ]);
2321
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
2322
+ 3, 4,
2323
+ ]);
2324
+ expect(stateVariables["/_point3"].stateValues.xs[0]).eq(1);
2325
+ expect(stateVariables["/_point3"].stateValues.xs[1]).eq(2);
2326
+ });
2327
+
2328
+ cy.log("move line segment to 45 degrees");
2329
+ cy.window().then(async (win) => {
2330
+ win.callAction1({
2331
+ actionName: "moveLineSegment",
2332
+ componentName: "/_linesegment1",
2333
+ args: {
2334
+ point1coords: [-4, 4],
2335
+ point2coords: [4, -4],
2336
+ },
2337
+ });
2338
+
2339
+ cy.get(cesc("#\\/ep1a") + " .mjx-mrow").should(
2340
+ "contain.text",
2341
+ `(${nInDOM(-4)},${nInDOM(4)})`,
2342
+ );
2343
+
2344
+ cy.window().then(async (win) => {
2345
+ let stateVariables = await win.returnAllStateVariables1();
2346
+
2347
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
2348
+ -4, 4,
2349
+ ]);
2350
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
2351
+ 4, -4,
2352
+ ]);
2353
+
2354
+ let xorig = -5;
2355
+ let yorig = 2;
2356
+ let temp = (xorig - yorig) / 2;
2357
+ if (temp > 4) {
2358
+ temp = 4;
2359
+ } else if (temp < -4) {
2360
+ temp = -4;
2361
+ }
2362
+ let p5x = temp;
2363
+ let p5y = -temp;
2364
+
2365
+ expect(stateVariables["/_point3"].stateValues.xs[0]).closeTo(
2366
+ p5x,
2367
+ 1e-12,
2368
+ );
2369
+ expect(stateVariables["/_point3"].stateValues.xs[1]).closeTo(
2370
+ p5y,
2371
+ 1e-12,
2372
+ );
2373
+ });
2374
+ });
2375
+
2376
+ cy.log("move point");
2377
+ cy.window().then(async (win) => {
2378
+ let xorig = 10;
2379
+ let yorig = 1;
2380
+
2381
+ win.callAction1({
2382
+ actionName: "movePoint",
2383
+ componentName: "/_point3",
2384
+ args: { x: xorig, y: yorig },
2385
+ });
2386
+
2387
+ let temp = (xorig - yorig) / 2;
2388
+ if (temp > 4) {
2389
+ temp = 4;
2390
+ } else if (temp < -4) {
2391
+ temp = -4;
2392
+ }
2393
+ let p5x = temp;
2394
+ let p5y = -temp;
2395
+
2396
+ cy.get(cesc("#\\/p3a") + " .mjx-mrow").should(
2397
+ "contain.text",
2398
+ `(${nInDOM(p5x)},${nInDOM(p5y)})`,
2399
+ );
2400
+
2401
+ cy.window().then(async (win) => {
2402
+ let stateVariables = await win.returnAllStateVariables1();
2403
+ expect(stateVariables["/_point3"].stateValues.xs[0]).closeTo(
2404
+ p5x,
2405
+ 1e-12,
2406
+ );
2407
+ expect(stateVariables["/_point3"].stateValues.xs[1]).closeTo(
2408
+ p5y,
2409
+ 1e-12,
2410
+ );
2411
+ });
2412
+ });
2413
+
2414
+ cy.log("move point");
2415
+ cy.window().then(async (win) => {
2416
+ let xorig = 9;
2417
+ let yorig = 7;
2418
+
2419
+ win.callAction1({
2420
+ actionName: "movePoint",
2421
+ componentName: "/_point3",
2422
+ args: { x: xorig, y: yorig },
2423
+ });
2424
+
2425
+ let temp = (xorig - yorig) / 2;
2426
+ if (temp > 4) {
2427
+ temp = 4;
2428
+ } else if (temp < -4) {
2429
+ temp = -4;
2430
+ }
2431
+ let p5x = temp;
2432
+ let p5y = -temp;
2433
+
2434
+ cy.get(cesc("#\\/p3a") + " .mjx-mrow").should(
2435
+ "contain.text",
2436
+ `(${nInDOM(p5x)},${nInDOM(p5y)})`,
2437
+ );
2438
+
2439
+ cy.window().then(async (win) => {
2440
+ let stateVariables = await win.returnAllStateVariables1();
2441
+ expect(stateVariables["/_point3"].stateValues.xs[0]).closeTo(
2442
+ p5x,
2443
+ 1e-12,
2444
+ );
2445
+ expect(stateVariables["/_point3"].stateValues.xs[1]).closeTo(
2446
+ p5y,
2447
+ 1e-12,
2448
+ );
2449
+ });
2450
+ });
2451
+
2452
+ cy.log("move point");
2453
+ cy.window().then(async (win) => {
2454
+ let xorig = -9;
2455
+ let yorig = 7;
2456
+
2457
+ win.callAction1({
2458
+ actionName: "movePoint",
2459
+ componentName: "/_point3",
2460
+ args: { x: xorig, y: yorig },
2461
+ });
2462
+
2463
+ let temp = (xorig - yorig) / 2;
2464
+ if (temp > 4) {
2465
+ temp = 4;
2466
+ } else if (temp < -4) {
2467
+ temp = -4;
2468
+ }
2469
+ let p5x = temp;
2470
+ let p5y = -temp;
2471
+
2472
+ cy.get(cesc("#\\/p3a") + " .mjx-mrow").should(
2473
+ "contain.text",
2474
+ `(${nInDOM(p5x)},${nInDOM(p5y)})`,
2475
+ );
2476
+
2477
+ cy.window().then(async (win) => {
2478
+ let stateVariables = await win.returnAllStateVariables1();
2479
+ expect(stateVariables["/_point3"].stateValues.xs[0]).closeTo(
2480
+ p5x,
2481
+ 1e-12,
2482
+ );
2483
+ expect(stateVariables["/_point3"].stateValues.xs[1]).closeTo(
2484
+ p5y,
2485
+ 1e-12,
2486
+ );
2487
+ });
2488
+ });
2489
+ });
2490
+
2491
+ it("attract to linesegment", () => {
2492
+ cy.window().then(async (win) => {
2493
+ win.postMessage(
2494
+ {
2495
+ doenetML: `
2496
+ <text>a</text>
2497
+ <graph>
2498
+ <point>(1,2)</point>
2499
+ <point>(3,4)</point>
2500
+ <linesegment endpoints="$_point1 $_point2" />
2501
+
2502
+ <point x="-5" y="2">
2503
+ <constraints>
2504
+ <attractTo><copy target="_linesegment1" /></attractTo>
2505
+ </constraints>
2506
+ </point>
2507
+ </graph>
2508
+ <copy target="_linesegment1" prop="endpoint1" assignNames="ep1a" />
2509
+ <copy target="_point3" assignNames="p3a" />
2510
+ `,
2511
+ },
2512
+ "*",
2513
+ );
2514
+ });
2515
+
2516
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
2517
+
2518
+ cy.log("check initial values");
2519
+
2520
+ cy.get(cesc("#\\/ep1a") + " .mjx-mrow").should(
2521
+ "contain.text",
2522
+ `(${nInDOM(1)},${nInDOM(2)})`,
2523
+ );
2524
+
2525
+ cy.window().then(async (win) => {
2526
+ let stateVariables = await win.returnAllStateVariables1();
2527
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
2528
+ 1, 2,
2529
+ ]);
2530
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
2531
+ 3, 4,
2532
+ ]);
2533
+ expect(stateVariables["/_point3"].stateValues.xs[0]).eq(-5);
2534
+ expect(stateVariables["/_point3"].stateValues.xs[1]).eq(2);
2535
+ });
2536
+
2537
+ cy.log("move line segment to 45 degrees");
2538
+ cy.window().then(async (win) => {
2539
+ win.callAction1({
2540
+ actionName: "moveLineSegment",
2541
+ componentName: "/_linesegment1",
2542
+ args: {
2543
+ point1coords: [-4, 4],
2544
+ point2coords: [4, -4],
2545
+ },
2546
+ });
2547
+
2548
+ cy.get(cesc("#\\/ep1a") + " .mjx-mrow").should(
2549
+ "contain.text",
2550
+ `(${nInDOM(-4)},${nInDOM(4)})`,
2551
+ );
2552
+
2553
+ cy.window().then(async (win) => {
2554
+ let stateVariables = await win.returnAllStateVariables1();
2555
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
2556
+ -4, 4,
2557
+ ]);
2558
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
2559
+ 4, -4,
2560
+ ]);
2561
+ expect(stateVariables["/_point3"].stateValues.xs[0]).eq(-5);
2562
+ expect(stateVariables["/_point3"].stateValues.xs[1]).eq(2);
2563
+ });
2564
+ });
2565
+
2566
+ cy.log("move point");
2567
+ cy.window().then(async (win) => {
2568
+ let xorig = 3.3;
2569
+ let yorig = -3.6;
2570
+
2571
+ win.callAction1({
2572
+ actionName: "movePoint",
2573
+ componentName: "/_point3",
2574
+ args: { x: xorig, y: yorig },
2575
+ });
2576
+
2577
+ let temp = (xorig - yorig) / 2;
2578
+ if (temp > 4) {
2579
+ temp = 4;
2580
+ } else if (temp < -4) {
2581
+ temp = -4;
2582
+ }
2583
+ let p5x = temp;
2584
+ let p5y = -temp;
2585
+
2586
+ cy.get(cesc("#\\/p3a") + " .mjx-mrow").should(
2587
+ "contain.text",
2588
+ `(${nInDOM(p5x)},${nInDOM(p5y)})`,
2589
+ );
2590
+
2591
+ cy.window().then(async (win) => {
2592
+ let stateVariables = await win.returnAllStateVariables1();
2593
+ expect(stateVariables["/_point3"].stateValues.xs[0]).closeTo(
2594
+ p5x,
2595
+ 1e-12,
2596
+ );
2597
+ expect(stateVariables["/_point3"].stateValues.xs[1]).closeTo(
2598
+ p5y,
2599
+ 1e-12,
2600
+ );
2601
+ });
2602
+ });
2603
+
2604
+ cy.log("move point");
2605
+ cy.window().then(async (win) => {
2606
+ let xorig = 4.3;
2607
+ let yorig = -4.6;
2608
+
2609
+ win.callAction1({
2610
+ actionName: "movePoint",
2611
+ componentName: "/_point3",
2612
+ args: { x: xorig, y: yorig },
2613
+ });
2614
+
2615
+ cy.get(cesc("#\\/p3a") + " .mjx-mrow").should(
2616
+ "contain.text",
2617
+ `(${nInDOM(xorig)},${nInDOM(yorig)})`,
2618
+ );
2619
+
2620
+ cy.window().then(async (win) => {
2621
+ let stateVariables = await win.returnAllStateVariables1();
2622
+ expect(stateVariables["/_point3"].stateValues.xs[0]).closeTo(
2623
+ 4.3,
2624
+ 1e-12,
2625
+ );
2626
+ expect(stateVariables["/_point3"].stateValues.xs[1]).closeTo(
2627
+ -4.6,
2628
+ 1e-12,
2629
+ );
2630
+ });
2631
+ });
2632
+
2633
+ cy.log("move point");
2634
+ cy.window().then(async (win) => {
2635
+ let xorig = -2.4;
2636
+ let yorig = 2.8;
2637
+
2638
+ win.callAction1({
2639
+ actionName: "movePoint",
2640
+ componentName: "/_point3",
2641
+ args: { x: xorig, y: yorig },
2642
+ });
2643
+
2644
+ let temp = (xorig - yorig) / 2;
2645
+ if (temp > 4) {
2646
+ temp = 4;
2647
+ } else if (temp < -4) {
2648
+ temp = -4;
2649
+ }
2650
+ let p5x = temp;
2651
+ let p5y = -temp;
2652
+
2653
+ cy.get(cesc("#\\/p3a") + " .mjx-mrow").should(
2654
+ "contain.text",
2655
+ `(${nInDOM(Math.round(p5x * 1000) / 1000)},${nInDOM(
2656
+ Math.round(p5y * 1000) / 1000,
2657
+ )})`,
2658
+ );
2659
+
2660
+ cy.window().then(async (win) => {
2661
+ let stateVariables = await win.returnAllStateVariables1();
2662
+ expect(stateVariables["/_point3"].stateValues.xs[0]).closeTo(
2663
+ p5x,
2664
+ 1e-12,
2665
+ );
2666
+ expect(stateVariables["/_point3"].stateValues.xs[1]).closeTo(
2667
+ p5y,
2668
+ 1e-12,
2669
+ );
2670
+ });
2671
+ });
2672
+
2673
+ cy.log("move point");
2674
+ cy.window().then(async (win) => {
2675
+ let xorig = -4.2;
2676
+ let yorig = 4.3;
2677
+
2678
+ win.callAction1({
2679
+ actionName: "movePoint",
2680
+ componentName: "/_point3",
2681
+ args: { x: xorig, y: yorig },
2682
+ });
2683
+
2684
+ let temp = (xorig - yorig) / 2;
2685
+ if (temp > 4) {
2686
+ temp = 4;
2687
+ } else if (temp < -4) {
2688
+ temp = -4;
2689
+ }
2690
+ let p5x = temp;
2691
+ let p5y = -temp;
2692
+
2693
+ cy.get(cesc("#\\/p3a") + " .mjx-mrow").should(
2694
+ "contain.text",
2695
+ `(${nInDOM(p5x)},${nInDOM(p5y)})`,
2696
+ );
2697
+
2698
+ cy.window().then(async (win) => {
2699
+ let stateVariables = await win.returnAllStateVariables1();
2700
+ expect(stateVariables["/_point3"].stateValues.xs[0]).closeTo(
2701
+ p5x,
2702
+ 1e-12,
2703
+ );
2704
+ expect(stateVariables["/_point3"].stateValues.xs[1]).closeTo(
2705
+ p5y,
2706
+ 1e-12,
2707
+ );
2708
+ });
2709
+ });
2710
+ });
2711
+
2712
+ it("constrain to linesegment, different scales from graph", () => {
2713
+ cy.window().then(async (win) => {
2714
+ win.postMessage(
2715
+ {
2716
+ doenetML: `
2717
+ <text>a</text>
2718
+ <graph xmin="-110" xmax="110" ymin="-0.11" ymax="0.11">
2719
+ <linesegment endpoints="(-1,-0.05) (1,0.05)" name="l" />
2720
+ <point x="100" y="0" name="P">
2721
+ <constraints>
2722
+ <constrainTo relativeToGraphScales><copy target="l" /></constrainTo>
2723
+ </constraints>
2724
+ </point>
2725
+ </graph>
2726
+ <copy target="P" assignNames="P1a" />
2727
+ `,
2728
+ },
2729
+ "*",
2730
+ );
2731
+ });
2732
+
2733
+ // use this to wait for page to load
2734
+ cy.get(cesc("#\\/_text1")).should("have.text", "a");
2735
+
2736
+ cy.log(`point on line segment, close to origin`);
2737
+
2738
+ cy.get(cesc("#\\/P1a") + " .mjx-mrow").should("contain.text", ",0.00");
2739
+
2740
+ cy.window().then(async (win) => {
2741
+ let stateVariables = await win.returnAllStateVariables1();
2742
+ let x = stateVariables["/P"].stateValues.xs[0];
2743
+ let y = stateVariables["/P"].stateValues.xs[1];
2744
+
2745
+ expect(y).greaterThan(0);
2746
+ expect(y).lessThan(0.01);
2747
+
2748
+ expect(x).closeTo(20 * y, 1e-10);
2749
+ });
2750
+
2751
+ cy.log(`move point`);
2752
+ cy.window().then(async (win) => {
2753
+ win.callAction1({
2754
+ actionName: "movePoint",
2755
+ componentName: "/P",
2756
+ args: { x: -100, y: 0.05 },
2757
+ });
2758
+
2759
+ cy.get(cesc("#\\/P1a") + " .mjx-mrow").should("contain.text", ",0.04");
2760
+
2761
+ cy.window().then(async (win) => {
2762
+ let stateVariables = await win.returnAllStateVariables1();
2763
+ let x = stateVariables["/P"].stateValues.xs[0];
2764
+ let y = stateVariables["/P"].stateValues.xs[1];
2765
+ expect(y).lessThan(0.05);
2766
+ expect(y).greaterThan(0.04);
2767
+ expect(x).closeTo(20 * y, 1e-10);
2768
+ });
2769
+ });
2770
+
2771
+ cy.log(`move point past endpoint`);
2772
+ cy.window().then(async (win) => {
2773
+ win.callAction1({
2774
+ actionName: "movePoint",
2775
+ componentName: "/P",
2776
+ args: { x: -100, y: 0.1 },
2777
+ });
2778
+
2779
+ cy.get(cesc("#\\/P1a") + " .mjx-mrow").should("contain.text", ",0.05");
2780
+ cy.window().then(async (win) => {
2781
+ let stateVariables = await win.returnAllStateVariables1();
2782
+ let x = stateVariables["/P"].stateValues.xs[0];
2783
+ let y = stateVariables["/P"].stateValues.xs[1];
2784
+ expect(y).eq(0.05);
2785
+ expect(x).closeTo(20 * y, 1e-10);
2786
+ });
2787
+ });
2788
+ });
2789
+
2790
+ it("copy endpoints of line segment", () => {
2791
+ cy.window().then(async (win) => {
2792
+ win.postMessage(
2793
+ {
2794
+ doenetML: `
2795
+ <text>a</text>
2796
+ <graph>
2797
+ <linesegment endpoints="(1,2) (3,4)"/>
2798
+ </graph>
2799
+ <graph>
2800
+ <copy prop="endpoint1" target="_linesegment1" assignNames="p1" />
2801
+ <copy prop="endpoint2" target="_linesegment1" assignNames="p2" />
2802
+ </graph>
2803
+ <graph>
2804
+ <copy prop="endpoints" target="_linesegment1" assignNames="p1a p2a" />
2805
+ </graph>
2806
+ <copy prop="endpoint1" target="_linesegment1" assignNames="p1b" />
2807
+ <copy prop="endpoint2" target="_linesegment1" assignNames="p2b" />
2808
+ `,
2809
+ },
2810
+ "*",
2811
+ );
2812
+ });
2813
+
2814
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
2815
+
2816
+ cy.window().then(async (win) => {
2817
+ let stateVariables = await win.returnAllStateVariables1();
2818
+ let p1x = 1;
2819
+ let p1y = 2;
2820
+ let p2x = 3;
2821
+ let p2y = 4;
2822
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
2823
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
2824
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
2825
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
2826
+ expect(stateVariables["/p1a"].stateValues.xs[0]).eq(p1x);
2827
+ expect(stateVariables["/p1a"].stateValues.xs[1]).eq(p1y);
2828
+ expect(stateVariables["/p2a"].stateValues.xs[0]).eq(p2x);
2829
+ expect(stateVariables["/p2a"].stateValues.xs[1]).eq(p2y);
2830
+
2831
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
2832
+ "contain.text",
2833
+ `(${nInDOM(p1x)},${nInDOM(p1y)})`,
2834
+ );
2835
+ });
2836
+
2837
+ cy.log("move first individually copied point");
2838
+ cy.window().then(async (win) => {
2839
+ let p1x = -2;
2840
+ let p1y = -5;
2841
+ win.callAction1({
2842
+ actionName: "movePoint",
2843
+ componentName: "/p1",
2844
+ args: { x: p1x, y: p1y },
2845
+ });
2846
+
2847
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
2848
+ "contain.text",
2849
+ `(${nInDOM(p1x)},${nInDOM(p1y)})`,
2850
+ );
2851
+
2852
+ cy.window().then(async (win) => {
2853
+ let stateVariables = await win.returnAllStateVariables1();
2854
+ let p2x = 3;
2855
+ let p2y = 4;
2856
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
2857
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
2858
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
2859
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
2860
+ expect(stateVariables["/p1a"].stateValues.xs[0]).eq(p1x);
2861
+ expect(stateVariables["/p1a"].stateValues.xs[1]).eq(p1y);
2862
+ expect(stateVariables["/p2a"].stateValues.xs[0]).eq(p2x);
2863
+ expect(stateVariables["/p2a"].stateValues.xs[1]).eq(p2y);
2864
+ });
2865
+ });
2866
+
2867
+ cy.log("move second individually copied point");
2868
+ cy.window().then(async (win) => {
2869
+ let p2x = 8;
2870
+ let p2y = -1;
2871
+ win.callAction1({
2872
+ actionName: "movePoint",
2873
+ componentName: "/p2",
2874
+ args: { x: p2x, y: p2y },
2875
+ });
2876
+
2877
+ cy.get(cesc("#\\/p2b") + " .mjx-mrow").should(
2878
+ "contain.text",
2879
+ `(${nInDOM(p2x)},${nInDOM(p2y)})`,
2880
+ );
2881
+
2882
+ cy.window().then(async (win) => {
2883
+ let stateVariables = await win.returnAllStateVariables1();
2884
+ let p1x = -2;
2885
+ let p1y = -5;
2886
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
2887
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
2888
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
2889
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
2890
+ expect(stateVariables["/p1a"].stateValues.xs[0]).eq(p1x);
2891
+ expect(stateVariables["/p1a"].stateValues.xs[1]).eq(p1y);
2892
+ expect(stateVariables["/p2a"].stateValues.xs[0]).eq(p2x);
2893
+ expect(stateVariables["/p2a"].stateValues.xs[1]).eq(p2y);
2894
+ });
2895
+ });
2896
+
2897
+ cy.log("move second array-copied point");
2898
+ cy.window().then(async (win) => {
2899
+ let p2x = -6;
2900
+ let p2y = 4;
2901
+ win.callAction1({
2902
+ actionName: "movePoint",
2903
+ componentName: "/p2a",
2904
+ args: { x: p2x, y: p2y },
2905
+ });
2906
+
2907
+ cy.get(cesc("#\\/p2b") + " .mjx-mrow").should(
2908
+ "contain.text",
2909
+ `(${nInDOM(p2x)},${nInDOM(p2y)})`,
2910
+ );
2911
+
2912
+ cy.window().then(async (win) => {
2913
+ let stateVariables = await win.returnAllStateVariables1();
2914
+ let p1x = -2;
2915
+ let p1y = -5;
2916
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
2917
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
2918
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
2919
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
2920
+ expect(stateVariables["/p1a"].stateValues.xs[0]).eq(p1x);
2921
+ expect(stateVariables["/p1a"].stateValues.xs[1]).eq(p1y);
2922
+ expect(stateVariables["/p2a"].stateValues.xs[0]).eq(p2x);
2923
+ expect(stateVariables["/p2a"].stateValues.xs[1]).eq(p2y);
2924
+ });
2925
+ });
2926
+
2927
+ cy.log("move first array-copied point");
2928
+ cy.window().then(async (win) => {
2929
+ let p1x = 0;
2930
+ let p1y = 7;
2931
+ win.callAction1({
2932
+ actionName: "movePoint",
2933
+ componentName: "/p1a",
2934
+ args: { x: p1x, y: p1y },
2935
+ });
2936
+
2937
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
2938
+ "contain.text",
2939
+ `(${nInDOM(p1x)},${nInDOM(p1y)})`,
2940
+ );
2941
+
2942
+ cy.window().then(async (win) => {
2943
+ let stateVariables = await win.returnAllStateVariables1();
2944
+ let p2x = -6;
2945
+ let p2y = 4;
2946
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
2947
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
2948
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
2949
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
2950
+ expect(stateVariables["/p1a"].stateValues.xs[0]).eq(p1x);
2951
+ expect(stateVariables["/p1a"].stateValues.xs[1]).eq(p1y);
2952
+ expect(stateVariables["/p2a"].stateValues.xs[0]).eq(p2x);
2953
+ expect(stateVariables["/p2a"].stateValues.xs[1]).eq(p2y);
2954
+ });
2955
+ });
2956
+
2957
+ cy.log("move line up and to the right");
2958
+ cy.window().then(async (win) => {
2959
+ let stateVariables = await win.returnAllStateVariables1();
2960
+
2961
+ let point1coords = [
2962
+ stateVariables["/_linesegment1"].stateValues.endpoints[0][0],
2963
+ stateVariables["/_linesegment1"].stateValues.endpoints[0][1],
2964
+ ];
2965
+ let point2coords = [
2966
+ stateVariables["/_linesegment1"].stateValues.endpoints[1][0],
2967
+ stateVariables["/_linesegment1"].stateValues.endpoints[1][1],
2968
+ ];
2969
+
2970
+ let moveX = 4;
2971
+ let moveY = 2;
2972
+
2973
+ point1coords[0] = me.fromAst(point1coords[0]).add(moveX).simplify().tree;
2974
+ point1coords[1] = me.fromAst(point1coords[1]).add(moveY).simplify().tree;
2975
+ point2coords[0] = me.fromAst(point2coords[0]).add(moveX).simplify().tree;
2976
+ point2coords[1] = me.fromAst(point2coords[1]).add(moveY).simplify().tree;
2977
+
2978
+ win.callAction1({
2979
+ actionName: "moveLineSegment",
2980
+ componentName: "/_linesegment1",
2981
+ args: {
2982
+ point1coords: point1coords,
2983
+ point2coords: point2coords,
2984
+ },
2985
+ });
2986
+
2987
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
2988
+ "contain.text",
2989
+ `(${nInDOM(point1coords[0]).substring(0, 4)}`,
2990
+ );
2991
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
2992
+ "contain.text",
2993
+ `,${nInDOM(point1coords[1]).substring(0, 4)}`,
2994
+ );
2995
+
2996
+ cy.window().then(async (win) => {
2997
+ let stateVariables = await win.returnAllStateVariables1();
2998
+
2999
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(point1coords[0]);
3000
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(point1coords[1]);
3001
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(point2coords[0]);
3002
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(point2coords[1]);
3003
+ expect(stateVariables["/p1a"].stateValues.xs[0]).eq(point1coords[0]);
3004
+ expect(stateVariables["/p1a"].stateValues.xs[1]).eq(point1coords[1]);
3005
+ expect(stateVariables["/p2a"].stateValues.xs[0]).eq(point2coords[0]);
3006
+ expect(stateVariables["/p2a"].stateValues.xs[1]).eq(point2coords[1]);
3007
+ });
3008
+ });
3009
+ });
3010
+
3011
+ it("new linesegment from copied endpoints of line segment", () => {
3012
+ cy.window().then(async (win) => {
3013
+ win.postMessage(
3014
+ {
3015
+ doenetML: `
3016
+ <text>a</text>
3017
+ <graph>
3018
+ <linesegment endpoints="(-1,-2) (-3,-4)" />
3019
+ </graph>
3020
+ <graph>
3021
+ <linesegment endpoints="$(_linesegment1.endpoints)" />
3022
+ <copy prop="endpoints" target="_linesegment1" assignNames="p1 p2" />
3023
+ </graph>
3024
+ <copy prop="endpoint1" target="_linesegment1" assignNames="p1b" />
3025
+ <copy prop="endpoint2" target="_linesegment1" assignNames="p2b" />
3026
+ `,
3027
+ },
3028
+ "*",
3029
+ );
3030
+ });
3031
+
3032
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
3033
+
3034
+ cy.window().then(async (win) => {
3035
+ let stateVariables = await win.returnAllStateVariables1();
3036
+ let p1x = -1;
3037
+ let p1y = -2;
3038
+ let p2x = -3;
3039
+ let p2y = -4;
3040
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
3041
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
3042
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
3043
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
3044
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
3045
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
3046
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
3047
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
3048
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3049
+ p1x,
3050
+ p1y,
3051
+ ]);
3052
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3053
+ p2x,
3054
+ p2y,
3055
+ ]);
3056
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3057
+ p1x,
3058
+ p1y,
3059
+ ]);
3060
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3061
+ p2x,
3062
+ p2y,
3063
+ ]);
3064
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
3065
+ "contain.text",
3066
+ `(${nInDOM(p1x)},${nInDOM(p1y)}`,
3067
+ );
3068
+ });
3069
+
3070
+ cy.log("move first line segment up and to the right");
3071
+ cy.window().then(async (win) => {
3072
+ let stateVariables = await win.returnAllStateVariables1();
3073
+
3074
+ let point1coords = [
3075
+ stateVariables["/_linesegment1"].stateValues.endpoints[0][0],
3076
+ stateVariables["/_linesegment1"].stateValues.endpoints[0][1],
3077
+ ];
3078
+ let point2coords = [
3079
+ stateVariables["/_linesegment1"].stateValues.endpoints[1][0],
3080
+ stateVariables["/_linesegment1"].stateValues.endpoints[1][1],
3081
+ ];
3082
+
3083
+ let moveX = 4;
3084
+ let moveY = 2;
3085
+
3086
+ point1coords[0] = me.fromAst(point1coords[0]).add(moveX).simplify().tree;
3087
+ point1coords[1] = me.fromAst(point1coords[1]).add(moveY).simplify().tree;
3088
+ point2coords[0] = me.fromAst(point2coords[0]).add(moveX).simplify().tree;
3089
+ point2coords[1] = me.fromAst(point2coords[1]).add(moveY).simplify().tree;
3090
+
3091
+ win.callAction1({
3092
+ actionName: "moveLineSegment",
3093
+ componentName: "/_linesegment1",
3094
+ args: {
3095
+ point1coords: point1coords,
3096
+ point2coords: point2coords,
3097
+ },
3098
+ });
3099
+
3100
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
3101
+ "contain.text",
3102
+ `(${nInDOM(point1coords[0]).substring(0, 4)}`,
3103
+ );
3104
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
3105
+ "contain.text",
3106
+ `,${nInDOM(point1coords[1]).substring(0, 4)}`,
3107
+ );
3108
+
3109
+ cy.window().then(async (win) => {
3110
+ let stateVariables = await win.returnAllStateVariables1();
3111
+
3112
+ let p1x = -1 + moveX;
3113
+ let p1y = -2 + moveY;
3114
+ let p2x = -3 + moveX;
3115
+ let p2y = -4 + moveY;
3116
+
3117
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
3118
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
3119
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
3120
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
3121
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
3122
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
3123
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
3124
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
3125
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3126
+ p1x,
3127
+ p1y,
3128
+ ]);
3129
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3130
+ p2x,
3131
+ p2y,
3132
+ ]);
3133
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3134
+ p1x,
3135
+ p1y,
3136
+ ]);
3137
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3138
+ p2x,
3139
+ p2y,
3140
+ ]);
3141
+ });
3142
+ });
3143
+
3144
+ cy.log("move second line segment up and to the left");
3145
+ cy.window().then(async (win) => {
3146
+ let stateVariables = await win.returnAllStateVariables1();
3147
+
3148
+ let point1coords = [
3149
+ stateVariables["/_linesegment2"].stateValues.endpoints[0][0],
3150
+ stateVariables["/_linesegment2"].stateValues.endpoints[0][1],
3151
+ ];
3152
+ let point2coords = [
3153
+ stateVariables["/_linesegment2"].stateValues.endpoints[1][0],
3154
+ stateVariables["/_linesegment2"].stateValues.endpoints[1][1],
3155
+ ];
3156
+
3157
+ let moveX = -7;
3158
+ let moveY = 3;
3159
+
3160
+ point1coords[0] = me.fromAst(point1coords[0]).add(moveX).simplify().tree;
3161
+ point1coords[1] = me.fromAst(point1coords[1]).add(moveY).simplify().tree;
3162
+ point2coords[0] = me.fromAst(point2coords[0]).add(moveX).simplify().tree;
3163
+ point2coords[1] = me.fromAst(point2coords[1]).add(moveY).simplify().tree;
3164
+
3165
+ win.callAction1({
3166
+ actionName: "moveLineSegment",
3167
+ componentName: "/_linesegment2",
3168
+ args: {
3169
+ point1coords: point1coords,
3170
+ point2coords: point2coords,
3171
+ },
3172
+ });
3173
+
3174
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
3175
+ "contain.text",
3176
+ `(${nInDOM(point1coords[0]).substring(0, 4)}`,
3177
+ );
3178
+ cy.get(cesc("#\\/p1b") + " .mjx-mrow").should(
3179
+ "contain.text",
3180
+ `,${nInDOM(point1coords[1]).substring(0, 4)}`,
3181
+ );
3182
+
3183
+ cy.window().then(async (win) => {
3184
+ let stateVariables = await win.returnAllStateVariables1();
3185
+
3186
+ moveX = 4 + moveX;
3187
+ moveY = 2 + moveY;
3188
+ let p1x = -1 + moveX;
3189
+ let p1y = -2 + moveY;
3190
+ let p2x = -3 + moveX;
3191
+ let p2y = -4 + moveY;
3192
+
3193
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
3194
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
3195
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
3196
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
3197
+ expect(stateVariables["/p1"].stateValues.xs[0]).eq(p1x);
3198
+ expect(stateVariables["/p1"].stateValues.xs[1]).eq(p1y);
3199
+ expect(stateVariables["/p2"].stateValues.xs[0]).eq(p2x);
3200
+ expect(stateVariables["/p2"].stateValues.xs[1]).eq(p2y);
3201
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3202
+ p1x,
3203
+ p1y,
3204
+ ]);
3205
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3206
+ p2x,
3207
+ p2y,
3208
+ ]);
3209
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3210
+ p1x,
3211
+ p1y,
3212
+ ]);
3213
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3214
+ p2x,
3215
+ p2y,
3216
+ ]);
3217
+ });
3218
+ });
3219
+ });
3220
+
3221
+ it("extracting endpoint coordinates of symmetric linesegment", () => {
3222
+ cy.window().then(async (win) => {
3223
+ win.postMessage(
3224
+ {
3225
+ doenetML: `
3226
+ <text>a</text>
3227
+ <graph>
3228
+ <linesegment endpoints="(1,2) ($(_linesegment1.endpointX1_2), $(_linesegment1.endpointX1_1))" />
3229
+ <point name="x1">
3230
+ (<extract prop="x"><copy prop="endpoint1" target="_linesegment1" /></extract>,
3231
+ <math fixed>3</math>)
3232
+ </point>
3233
+ <point name="x2">
3234
+ (<extract prop="x"><copy prop="endpoint2" target="_linesegment1" /></extract>,
3235
+ <math fixed>4</math>)
3236
+ </point>
3237
+ <point name="y1">
3238
+ (<math fixed>3</math>,
3239
+ <extract prop="y"><copy prop="endpoint1" target="_linesegment1" /></extract>)
3240
+ </point>
3241
+ <point name="y2">
3242
+ (<math fixed>4</math>,
3243
+ <extract prop="y"><copy prop="endpoint2" target="_linesegment1" /></extract>)
3244
+ </point>
3245
+ </graph>
3246
+ <copy prop="endpoint1" target="_linesegment1" assignNames="p1" />
3247
+ <copy prop="endpoint2" target="_linesegment1" assignNames="p2" />
3248
+ `,
3249
+ },
3250
+ "*",
3251
+ );
3252
+ });
3253
+
3254
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
3255
+
3256
+ let x = 1,
3257
+ y = 2;
3258
+
3259
+ cy.get(cesc("#\\/p1") + " .mjx-mrow").should(
3260
+ "contain.text",
3261
+ `(${nInDOM(x)},${nInDOM(y)})`,
3262
+ );
3263
+
3264
+ cy.window().then(async (win) => {
3265
+ let stateVariables = await win.returnAllStateVariables1();
3266
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3267
+ x,
3268
+ y,
3269
+ ]);
3270
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3271
+ y,
3272
+ x,
3273
+ ]);
3274
+ expect(stateVariables["/x1"].stateValues.xs[0]).eq(x);
3275
+ expect(stateVariables["/x2"].stateValues.xs[0]).eq(y);
3276
+ expect(stateVariables["/y1"].stateValues.xs[1]).eq(y);
3277
+ expect(stateVariables["/y2"].stateValues.xs[1]).eq(x);
3278
+ });
3279
+
3280
+ cy.log("move x point 1");
3281
+ cy.window().then(async (win) => {
3282
+ x = 3;
3283
+
3284
+ win.callAction1({
3285
+ actionName: "movePoint",
3286
+ componentName: "/x1",
3287
+ args: { x },
3288
+ });
3289
+
3290
+ cy.get(cesc("#\\/p1") + " .mjx-mrow").should(
3291
+ "contain.text",
3292
+ `(${nInDOM(x)},${nInDOM(y)})`,
3293
+ );
3294
+ cy.get(cesc("#\\/p2") + " .mjx-mrow").should(
3295
+ "contain.text",
3296
+ `(${nInDOM(y)},${nInDOM(x)})`,
3297
+ );
3298
+
3299
+ cy.window().then(async (win) => {
3300
+ let stateVariables = await win.returnAllStateVariables1();
3301
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3302
+ x,
3303
+ y,
3304
+ ]);
3305
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3306
+ y,
3307
+ x,
3308
+ ]);
3309
+ expect(stateVariables["/x1"].stateValues.xs[0]).eq(x);
3310
+ expect(stateVariables["/x2"].stateValues.xs[0]).eq(y);
3311
+ expect(stateVariables["/y1"].stateValues.xs[1]).eq(y);
3312
+ expect(stateVariables["/y2"].stateValues.xs[1]).eq(x);
3313
+ });
3314
+ });
3315
+
3316
+ cy.log("move x point 2");
3317
+ cy.window().then(async (win) => {
3318
+ y = 4;
3319
+
3320
+ win.callAction1({
3321
+ actionName: "movePoint",
3322
+ componentName: "/x2",
3323
+ args: { x: y },
3324
+ });
3325
+
3326
+ cy.get(cesc("#\\/p1") + " .mjx-mrow").should(
3327
+ "contain.text",
3328
+ `(${nInDOM(x)},${nInDOM(y)})`,
3329
+ );
3330
+ cy.get(cesc("#\\/p2") + " .mjx-mrow").should(
3331
+ "contain.text",
3332
+ `(${nInDOM(y)},${nInDOM(x)})`,
3333
+ );
3334
+
3335
+ cy.window().then(async (win) => {
3336
+ let stateVariables = await win.returnAllStateVariables1();
3337
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3338
+ x,
3339
+ y,
3340
+ ]);
3341
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3342
+ y,
3343
+ x,
3344
+ ]);
3345
+ expect(stateVariables["/x1"].stateValues.xs[0]).eq(x);
3346
+ expect(stateVariables["/x2"].stateValues.xs[0]).eq(y);
3347
+ expect(stateVariables["/y1"].stateValues.xs[1]).eq(y);
3348
+ expect(stateVariables["/y2"].stateValues.xs[1]).eq(x);
3349
+ });
3350
+ });
3351
+
3352
+ cy.log("move y point 1");
3353
+ cy.window().then(async (win) => {
3354
+ y = -6;
3355
+
3356
+ win.callAction1({
3357
+ actionName: "movePoint",
3358
+ componentName: "/y1",
3359
+ args: { y },
3360
+ });
3361
+
3362
+ cy.get(cesc("#\\/p1") + " .mjx-mrow").should(
3363
+ "contain.text",
3364
+ `(${nInDOM(x)},${nInDOM(y)})`,
3365
+ );
3366
+ cy.get(cesc("#\\/p2") + " .mjx-mrow").should(
3367
+ "contain.text",
3368
+ `(${nInDOM(y)},${nInDOM(x)})`,
3369
+ );
3370
+
3371
+ cy.window().then(async (win) => {
3372
+ let stateVariables = await win.returnAllStateVariables1();
3373
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3374
+ x,
3375
+ y,
3376
+ ]);
3377
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3378
+ y,
3379
+ x,
3380
+ ]);
3381
+ expect(stateVariables["/x1"].stateValues.xs[0]).eq(x);
3382
+ expect(stateVariables["/x2"].stateValues.xs[0]).eq(y);
3383
+ expect(stateVariables["/y1"].stateValues.xs[1]).eq(y);
3384
+ expect(stateVariables["/y2"].stateValues.xs[1]).eq(x);
3385
+ });
3386
+ });
3387
+
3388
+ cy.log("move y point 2");
3389
+ cy.window().then(async (win) => {
3390
+ x = -8;
3391
+
3392
+ win.callAction1({
3393
+ actionName: "movePoint",
3394
+ componentName: "/y2",
3395
+ args: { y: x },
3396
+ });
3397
+
3398
+ cy.get(cesc("#\\/p1") + " .mjx-mrow").should(
3399
+ "contain.text",
3400
+ `(${nInDOM(x)},${nInDOM(y)})`,
3401
+ );
3402
+ cy.get(cesc("#\\/p2") + " .mjx-mrow").should(
3403
+ "contain.text",
3404
+ `(${nInDOM(y)},${nInDOM(x)})`,
3405
+ );
3406
+
3407
+ cy.window().then(async (win) => {
3408
+ let stateVariables = await win.returnAllStateVariables1();
3409
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3410
+ x,
3411
+ y,
3412
+ ]);
3413
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3414
+ y,
3415
+ x,
3416
+ ]);
3417
+ expect(stateVariables["/x1"].stateValues.xs[0]).eq(x);
3418
+ expect(stateVariables["/x2"].stateValues.xs[0]).eq(y);
3419
+ expect(stateVariables["/y1"].stateValues.xs[1]).eq(y);
3420
+ expect(stateVariables["/y2"].stateValues.xs[1]).eq(x);
3421
+ });
3422
+ });
3423
+ });
3424
+
3425
+ it("three linesegments with mutual references", () => {
3426
+ cy.window().then(async (win) => {
3427
+ win.postMessage(
3428
+ {
3429
+ doenetML: `
3430
+ <text>a</text>
3431
+ <graph>
3432
+ <linesegment endpoints="$(_linesegment2.endpoint2{ createComponentOfType='point'}) (1,0)" />
3433
+ <linesegment endpoints="$(_linesegment3.endpoint2{ createComponentOfType='point'}) (3,2)" />
3434
+ <linesegment endpoints="$(_linesegment1.endpoint2{ createComponentOfType='point'}) (-1,4)" />
3435
+ </graph>
3436
+ <copy prop="endpoint1" target="_linesegment1" assignNames="p11" />
3437
+ <copy prop="endpoint2" target="_linesegment1" assignNames="p12" />
3438
+ <copy prop="endpoint1" target="_linesegment2" assignNames="p21" />
3439
+ <copy prop="endpoint2" target="_linesegment2" assignNames="p22" />
3440
+ <copy prop="endpoint1" target="_linesegment3" assignNames="p31" />
3441
+ <copy prop="endpoint2" target="_linesegment3" assignNames="p32" />
3442
+ `,
3443
+ },
3444
+ "*",
3445
+ );
3446
+ });
3447
+
3448
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
3449
+
3450
+ let x1 = 1,
3451
+ y1 = 0;
3452
+ let x2 = 3,
3453
+ y2 = 2;
3454
+ let x3 = -1,
3455
+ y3 = 4;
3456
+
3457
+ cy.get(cesc("#\\/p11") + " .mjx-mrow").should(
3458
+ "contain.text",
3459
+ `(${nInDOM(x2)},${nInDOM(y2)})`,
3460
+ );
3461
+
3462
+ cy.window().then(async (win) => {
3463
+ let stateVariables = await win.returnAllStateVariables1();
3464
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3465
+ x2,
3466
+ y2,
3467
+ ]);
3468
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3469
+ x1,
3470
+ y1,
3471
+ ]);
3472
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3473
+ x3,
3474
+ y3,
3475
+ ]);
3476
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3477
+ x2,
3478
+ y2,
3479
+ ]);
3480
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[0]).eqls([
3481
+ x1,
3482
+ y1,
3483
+ ]);
3484
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[1]).eqls([
3485
+ x3,
3486
+ y3,
3487
+ ]);
3488
+ });
3489
+
3490
+ cy.log("move point 1 of line segment 1");
3491
+ cy.window().then(async (win) => {
3492
+ x2 = 7;
3493
+ y2 = -3;
3494
+
3495
+ win.callAction1({
3496
+ actionName: "movePoint",
3497
+ componentName: "/p11",
3498
+ args: { x: x2, y: y2 },
3499
+ });
3500
+
3501
+ cy.get(cesc("#\\/p11") + " .mjx-mrow").should(
3502
+ "contain.text",
3503
+ `(${nInDOM(x2)},${nInDOM(y2)})`,
3504
+ );
3505
+
3506
+ cy.window().then(async (win) => {
3507
+ let stateVariables = await win.returnAllStateVariables1();
3508
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3509
+ x2,
3510
+ y2,
3511
+ ]);
3512
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3513
+ x1,
3514
+ y1,
3515
+ ]);
3516
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3517
+ x3,
3518
+ y3,
3519
+ ]);
3520
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3521
+ x2,
3522
+ y2,
3523
+ ]);
3524
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[0]).eqls([
3525
+ x1,
3526
+ y1,
3527
+ ]);
3528
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[1]).eqls([
3529
+ x3,
3530
+ y3,
3531
+ ]);
3532
+ });
3533
+ });
3534
+
3535
+ cy.log("move point 2 of line segment 1");
3536
+ cy.window().then(async (win) => {
3537
+ x1 = -1;
3538
+ y1 = -4;
3539
+
3540
+ win.callAction1({
3541
+ actionName: "movePoint",
3542
+ componentName: "/p12",
3543
+ args: { x: x1, y: y1 },
3544
+ });
3545
+
3546
+ cy.get(cesc("#\\/p12") + " .mjx-mrow").should(
3547
+ "contain.text",
3548
+ `(${nInDOM(x1)},${nInDOM(y1)})`,
3549
+ );
3550
+
3551
+ cy.window().then(async (win) => {
3552
+ let stateVariables = await win.returnAllStateVariables1();
3553
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3554
+ x2,
3555
+ y2,
3556
+ ]);
3557
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3558
+ x1,
3559
+ y1,
3560
+ ]);
3561
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3562
+ x3,
3563
+ y3,
3564
+ ]);
3565
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3566
+ x2,
3567
+ y2,
3568
+ ]);
3569
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[0]).eqls([
3570
+ x1,
3571
+ y1,
3572
+ ]);
3573
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[1]).eqls([
3574
+ x3,
3575
+ y3,
3576
+ ]);
3577
+ });
3578
+ });
3579
+
3580
+ cy.log("move point 1 of line segment 2");
3581
+ cy.window().then(async (win) => {
3582
+ x3 = 9;
3583
+ y3 = -8;
3584
+
3585
+ win.callAction1({
3586
+ actionName: "movePoint",
3587
+ componentName: "/p21",
3588
+ args: { x: x3, y: y3 },
3589
+ });
3590
+
3591
+ cy.get(cesc("#\\/p21") + " .mjx-mrow").should(
3592
+ "contain.text",
3593
+ `(${nInDOM(x3)},${nInDOM(y3)})`,
3594
+ );
3595
+
3596
+ cy.window().then(async (win) => {
3597
+ let stateVariables = await win.returnAllStateVariables1();
3598
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3599
+ x2,
3600
+ y2,
3601
+ ]);
3602
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3603
+ x1,
3604
+ y1,
3605
+ ]);
3606
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3607
+ x3,
3608
+ y3,
3609
+ ]);
3610
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3611
+ x2,
3612
+ y2,
3613
+ ]);
3614
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[0]).eqls([
3615
+ x1,
3616
+ y1,
3617
+ ]);
3618
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[1]).eqls([
3619
+ x3,
3620
+ y3,
3621
+ ]);
3622
+ });
3623
+ });
3624
+
3625
+ cy.log("move point 2 of line segment 2");
3626
+ cy.window().then(async (win) => {
3627
+ x2 = 3;
3628
+ y2 = 2;
3629
+
3630
+ win.callAction1({
3631
+ actionName: "movePoint",
3632
+ componentName: "/p22",
3633
+ args: { x: x2, y: y2 },
3634
+ });
3635
+
3636
+ cy.get(cesc("#\\/p22") + " .mjx-mrow").should(
3637
+ "contain.text",
3638
+ `(${nInDOM(x2)},${nInDOM(y2)})`,
3639
+ );
3640
+
3641
+ cy.window().then(async (win) => {
3642
+ let stateVariables = await win.returnAllStateVariables1();
3643
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3644
+ x2,
3645
+ y2,
3646
+ ]);
3647
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3648
+ x1,
3649
+ y1,
3650
+ ]);
3651
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3652
+ x3,
3653
+ y3,
3654
+ ]);
3655
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3656
+ x2,
3657
+ y2,
3658
+ ]);
3659
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[0]).eqls([
3660
+ x1,
3661
+ y1,
3662
+ ]);
3663
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[1]).eqls([
3664
+ x3,
3665
+ y3,
3666
+ ]);
3667
+ });
3668
+ });
3669
+
3670
+ cy.log("move point 1 of line segment 3");
3671
+ cy.window().then(async (win) => {
3672
+ x1 = -5;
3673
+ y1 = 8;
3674
+
3675
+ win.callAction1({
3676
+ actionName: "movePoint",
3677
+ componentName: "/p31",
3678
+ args: { x: x1, y: y1 },
3679
+ });
3680
+
3681
+ cy.get(cesc("#\\/p31") + " .mjx-mrow").should(
3682
+ "contain.text",
3683
+ `(${nInDOM(x1)},${nInDOM(y1)})`,
3684
+ );
3685
+
3686
+ cy.window().then(async (win) => {
3687
+ let stateVariables = await win.returnAllStateVariables1();
3688
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3689
+ x2,
3690
+ y2,
3691
+ ]);
3692
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3693
+ x1,
3694
+ y1,
3695
+ ]);
3696
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3697
+ x3,
3698
+ y3,
3699
+ ]);
3700
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3701
+ x2,
3702
+ y2,
3703
+ ]);
3704
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[0]).eqls([
3705
+ x1,
3706
+ y1,
3707
+ ]);
3708
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[1]).eqls([
3709
+ x3,
3710
+ y3,
3711
+ ]);
3712
+ });
3713
+ });
3714
+
3715
+ cy.log("move point 2 of line segment 3");
3716
+ cy.window().then(async (win) => {
3717
+ let stateVariables = await win.returnAllStateVariables1();
3718
+
3719
+ x3 = 0;
3720
+ y3 = -5;
3721
+
3722
+ win.callAction1({
3723
+ actionName: "movePoint",
3724
+ componentName: "/p32",
3725
+ args: { x: x3, y: y3 },
3726
+ });
3727
+
3728
+ cy.get(cesc("#\\/p32") + " .mjx-mrow").should(
3729
+ "contain.text",
3730
+ `(${nInDOM(x3)},${nInDOM(y3)})`,
3731
+ );
3732
+
3733
+ cy.window().then(async (win) => {
3734
+ let stateVariables = await win.returnAllStateVariables1();
3735
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[0]).eqls([
3736
+ x2,
3737
+ y2,
3738
+ ]);
3739
+ expect(stateVariables["/_linesegment1"].stateValues.endpoints[1]).eqls([
3740
+ x1,
3741
+ y1,
3742
+ ]);
3743
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[0]).eqls([
3744
+ x3,
3745
+ y3,
3746
+ ]);
3747
+ expect(stateVariables["/_linesegment2"].stateValues.endpoints[1]).eqls([
3748
+ x2,
3749
+ y2,
3750
+ ]);
3751
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[0]).eqls([
3752
+ x1,
3753
+ y1,
3754
+ ]);
3755
+ expect(stateVariables["/_linesegment3"].stateValues.endpoints[1]).eqls([
3756
+ x3,
3757
+ y3,
3758
+ ]);
3759
+ });
3760
+ });
3761
+ });
3762
+
3763
+ it("copy propIndex of points", () => {
3764
+ cy.window().then(async (win) => {
3765
+ win.postMessage(
3766
+ {
3767
+ doenetML: `
3768
+ <text>a</text>
3769
+ <graph>
3770
+ <linesegment endpoints="(2,-3) (3,4)" />
3771
+ </graph>
3772
+
3773
+ <p><mathinput name="n" /></p>
3774
+
3775
+ <p><copy prop="endpoints" target="_linesegment1" propIndex="$n" assignNames="P1 P2" /></p>
3776
+
3777
+ <p><copy prop="endpoint2" target="_linesegment1" propIndex="$n" assignNames="x" /></p>
3778
+ `,
3779
+ },
3780
+ "*",
3781
+ );
3782
+ });
3783
+
3784
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
3785
+
3786
+ let t1x = 2,
3787
+ t1y = -3;
3788
+ let t2x = 3,
3789
+ t2y = 4;
3790
+
3791
+ cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist");
3792
+ cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist");
3793
+ cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist");
3794
+
3795
+ cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true });
3796
+ cy.get(cesc("#\\/P1") + " .mjx-mrow").should(
3797
+ "contain.text",
3798
+ `(${nInDOM(t1x)},${nInDOM(t1y)})`,
3799
+ );
3800
+ cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist");
3801
+ cy.get(cesc("#\\/x") + " .mjx-mrow").should(
3802
+ "contain.text",
3803
+ `${nInDOM(t2x)}`,
3804
+ );
3805
+
3806
+ cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", {
3807
+ force: true,
3808
+ });
3809
+ cy.get(cesc("#\\/P1") + " .mjx-mrow").should(
3810
+ "contain.text",
3811
+ `(${nInDOM(t2x)},${nInDOM(t2y)})`,
3812
+ );
3813
+ cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist");
3814
+ cy.get(cesc("#\\/x") + " .mjx-mrow").should(
3815
+ "contain.text",
3816
+ `${nInDOM(t2y)}`,
3817
+ );
3818
+
3819
+ cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", {
3820
+ force: true,
3821
+ });
3822
+ cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist");
3823
+ cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist");
3824
+ cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist");
3825
+ });
3826
+
3827
+ it("copy propIndex of points, dot and array notation", () => {
3828
+ cy.window().then(async (win) => {
3829
+ win.postMessage(
3830
+ {
3831
+ doenetML: `
3832
+ <text>a</text>
3833
+ <graph>
3834
+ <linesegment endpoints="(2,-3) (3,4)" />
3835
+ </graph>
3836
+
3837
+ <p><mathinput name="n" /></p>
3838
+
3839
+ <p><copy source="_linesegment1.endpoints[$n]" assignNames="P1 P2" /></p>
3840
+
3841
+ <p><copy source="_linesegment1.endpoint2[$n]" assignNames="x" /></p>
3842
+ <p><copy source="_linesegment1.endpoints[2][$n]" assignNames="xa" /></p>
3843
+ `,
3844
+ },
3845
+ "*",
3846
+ );
3847
+ });
3848
+
3849
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
3850
+
3851
+ let t1x = 2,
3852
+ t1y = -3;
3853
+ let t2x = 3,
3854
+ t2y = 4;
3855
+
3856
+ cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist");
3857
+ cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist");
3858
+ cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist");
3859
+ cy.get(cesc("#\\/xa") + " .mjx-mrow").should("not.exist");
3860
+
3861
+ cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true });
3862
+ cy.get(cesc("#\\/P1") + " .mjx-mrow").should(
3863
+ "contain.text",
3864
+ `(${nInDOM(t1x)},${nInDOM(t1y)})`,
3865
+ );
3866
+ cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist");
3867
+ cy.get(cesc("#\\/x") + " .mjx-mrow").should(
3868
+ "contain.text",
3869
+ `${nInDOM(t2x)}`,
3870
+ );
3871
+ cy.get(cesc("#\\/xa") + " .mjx-mrow").should(
3872
+ "contain.text",
3873
+ `${nInDOM(t2x)}`,
3874
+ );
3875
+
3876
+ cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", {
3877
+ force: true,
3878
+ });
3879
+ cy.get(cesc("#\\/P1") + " .mjx-mrow").should(
3880
+ "contain.text",
3881
+ `(${nInDOM(t2x)},${nInDOM(t2y)})`,
3882
+ );
3883
+ cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist");
3884
+ cy.get(cesc("#\\/x") + " .mjx-mrow").should(
3885
+ "contain.text",
3886
+ `${nInDOM(t2y)}`,
3887
+ );
3888
+ cy.get(cesc("#\\/xa") + " .mjx-mrow").should(
3889
+ "contain.text",
3890
+ `${nInDOM(t2y)}`,
3891
+ );
3892
+
3893
+ cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", {
3894
+ force: true,
3895
+ });
3896
+ cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist");
3897
+ cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist");
3898
+ cy.get(cesc("#\\/x") + " .mjx-mrow").should("not.exist");
3899
+ cy.get(cesc("#\\/xa") + " .mjx-mrow").should("not.exist");
3900
+ });
3901
+
3902
+ it("lineSegment slope", () => {
3903
+ cy.window().then(async (win) => {
3904
+ win.postMessage(
3905
+ {
3906
+ doenetML: `
3907
+ <text>a</text>
3908
+ <graph>
3909
+ <point name="A">(3,4)</point>
3910
+ <point name="B">(7,-2)</point>
3911
+ <linesegment name="l" endpoints="$A $B" />
3912
+ </graph>
3913
+ <copy prop="slope" target="l" assignNames="slope" />
3914
+ `,
3915
+ },
3916
+ "*",
3917
+ );
3918
+ });
3919
+
3920
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
3921
+
3922
+ let t1x = 3,
3923
+ t1y = 4;
3924
+ let t2x = 7,
3925
+ t2y = -2;
3926
+ let m = (t1y - t2y) / (t1x - t2x);
3927
+
3928
+ cy.get(cesc("#\\/slope")).should("contain.text", String(m));
3929
+
3930
+ cy.window().then(async (win) => {
3931
+ let stateVariables = await win.returnAllStateVariables1();
3932
+ expect(stateVariables["/l"].stateValues.slope).eq(m);
3933
+ });
3934
+
3935
+ cy.window().then(async (win) => {
3936
+ t1x = 7;
3937
+ t1y = 3;
3938
+ m = (t1y - t2y) / (t1x - t2x);
3939
+ await win.callAction1({
3940
+ actionName: "movePoint",
3941
+ componentName: "/A",
3942
+ args: { x: t1x, y: t1y },
3943
+ });
3944
+
3945
+ cy.get(cesc("#\\/slope")).should("contain.text", "∞");
3946
+ });
3947
+
3948
+ cy.window().then(async (win) => {
3949
+ let stateVariables = await win.returnAllStateVariables1();
3950
+ expect(Math.abs(stateVariables["/l"].stateValues.slope)).eq(Infinity);
3951
+ });
3952
+
3953
+ cy.window().then(async (win) => {
3954
+ t2x = -9;
3955
+ t2y = 5;
3956
+ m = (t1y - t2y) / (t1x - t2x);
3957
+ await win.callAction1({
3958
+ actionName: "movePoint",
3959
+ componentName: "/B",
3960
+ args: { x: t2x, y: t2y },
3961
+ });
3962
+
3963
+ cy.get(cesc("#\\/slope")).should("contain.text", String(m));
3964
+ });
3965
+
3966
+ cy.window().then(async (win) => {
3967
+ let stateVariables = await win.returnAllStateVariables1();
3968
+ expect(stateVariables["/l"].stateValues.slope).eq(m);
3969
+ });
3970
+ });
3971
+
3972
+ it("lineSegment length", () => {
3973
+ cy.window().then(async (win) => {
3974
+ win.postMessage(
3975
+ {
3976
+ doenetML: `
3977
+ <text>a</text>
3978
+ <graph>
3979
+ <point name="A">(3,4)</point>
3980
+ <point name="B">(7,-2)</point>
3981
+ <linesegment name="l" endpoints="$A $B" />
3982
+ </graph>
3983
+ <copy prop="length" target="l" assignNames="length" displayDigits="10" />
3984
+ <point name="Ap" copySource="A" />
3985
+ <point name="Bp" copySource="B" />
3986
+ <mathinput name="milength" bindValueTo="$length" />
3987
+ <p><booleaninput name="bi"/><boolean copySource="bi" name="bi2" /></p>
3988
+ `,
3989
+ },
3990
+ "*",
3991
+ );
3992
+ });
3993
+
3994
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
3995
+
3996
+ let t1x = 3,
3997
+ t1y = 4;
3998
+ let t2x = 7,
3999
+ t2y = -2;
4000
+ let len = Math.sqrt((t1y - t2y) ** 2 + (t1x - t2x) ** 2);
4001
+
4002
+ cy.get(cesc("#\\/length")).should(
4003
+ "contain.text",
4004
+ String(Math.round(len * 10 ** 9) / 10 ** 9),
4005
+ );
4006
+ cy.get(cesc("#\\/Ap") + " .mjx-mrow")
4007
+ .eq(0)
4008
+ .should("have.text", "(3,4)");
4009
+ cy.get(cesc("#\\/Bp") + " .mjx-mrow")
4010
+ .eq(0)
4011
+ .should("have.text", "(7,−2)");
4012
+
4013
+ cy.window().then(async (win) => {
4014
+ let stateVariables = await win.returnAllStateVariables1();
4015
+ expect(stateVariables["/l"].stateValues.length).eq(len);
4016
+ });
4017
+
4018
+ cy.window().then(async (win) => {
4019
+ t1x = 7;
4020
+ t1y = 3;
4021
+ len = Math.sqrt((t1y - t2y) ** 2 + (t1x - t2x) ** 2);
4022
+ await win.callAction1({
4023
+ actionName: "movePoint",
4024
+ componentName: "/A",
4025
+ args: { x: t1x, y: t1y },
4026
+ });
4027
+
4028
+ cy.get(cesc("#\\/length")).should("contain.text", String(len));
4029
+ cy.get(cesc("#\\/Ap") + " .mjx-mrow")
4030
+ .eq(0)
4031
+ .should("have.text", "(7,3)");
4032
+ cy.get(cesc("#\\/Bp") + " .mjx-mrow")
4033
+ .eq(0)
4034
+ .should("have.text", "(7,−2)");
4035
+ });
4036
+
4037
+ cy.window().then(async (win) => {
4038
+ let stateVariables = await win.returnAllStateVariables1();
4039
+ expect(stateVariables["/l"].stateValues.length).eq(len);
4040
+ });
4041
+
4042
+ cy.get(cesc("#\\/milength") + " textarea").type(
4043
+ "{end}{backspace}10{enter}",
4044
+ { force: true },
4045
+ );
4046
+
4047
+ cy.get(cesc("#\\/length")).should("contain.text", "10");
4048
+ cy.get(cesc("#\\/Ap") + " .mjx-mrow")
4049
+ .eq(0)
4050
+ .should("have.text", "(7,5.5)");
4051
+ cy.get(cesc("#\\/Bp") + " .mjx-mrow")
4052
+ .eq(0)
4053
+ .should("have.text", "(7,−4.5)");
4054
+
4055
+ cy.window().then(async (win) => {
4056
+ let stateVariables = await win.returnAllStateVariables1();
4057
+ expect(stateVariables["/l"].stateValues.length).eq(10);
4058
+ });
4059
+
4060
+ cy.log("ignore requested negative length");
4061
+ cy.get(cesc("#\\/milength") + " textarea").type(
4062
+ "{end}{backspace}{backspace}-3{enter}",
4063
+ { force: true },
4064
+ );
4065
+ cy.get(cesc("#\\/bi")).click();
4066
+ cy.get(cesc("#\\/bi2")).should("have.text", "true"); // so know that core has responded to both requests
4067
+
4068
+ cy.get(cesc("#\\/length")).should("contain.text", "10");
4069
+ cy.get(cesc("#\\/Ap") + " .mjx-mrow")
4070
+ .eq(0)
4071
+ .should("have.text", "(7,5.5)");
4072
+ cy.get(cesc("#\\/Bp") + " .mjx-mrow")
4073
+ .eq(0)
4074
+ .should("have.text", "(7,−4.5)");
4075
+
4076
+ cy.window().then(async (win) => {
4077
+ let stateVariables = await win.returnAllStateVariables1();
4078
+ expect(stateVariables["/l"].stateValues.length).eq(10);
4079
+ });
4080
+
4081
+ cy.window().then(async (win) => {
4082
+ t1y = 5.5;
4083
+ t2x = -9;
4084
+ t2y = 5;
4085
+ len = Math.sqrt((t1y - t2y) ** 2 + (t1x - t2x) ** 2);
4086
+ await win.callAction1({
4087
+ actionName: "movePoint",
4088
+ componentName: "/B",
4089
+ args: { x: t2x, y: t2y },
4090
+ });
4091
+
4092
+ cy.get(cesc("#\\/length")).should(
4093
+ "contain.text",
4094
+ String(Math.round(len * 10 ** 8) / 10 ** 8),
4095
+ );
4096
+ cy.get(cesc("#\\/Ap") + " .mjx-mrow")
4097
+ .eq(0)
4098
+ .should("have.text", "(7,5.5)");
4099
+ cy.get(cesc("#\\/Bp") + " .mjx-mrow")
4100
+ .eq(0)
4101
+ .should("have.text", "(−9,5)");
4102
+ });
4103
+
4104
+ cy.window().then(async (win) => {
4105
+ let stateVariables = await win.returnAllStateVariables1();
4106
+ expect(stateVariables["/l"].stateValues.length).eq(len);
4107
+ });
4108
+ });
4109
+
4110
+ it("lineSegment symbolic length", () => {
4111
+ cy.window().then(async (win) => {
4112
+ win.postMessage(
4113
+ {
4114
+ doenetML: `
4115
+ <text>a</text>
4116
+ <linesegment name="l" endpoints="(x,y) (u,v)" />
4117
+ <copy prop="length" source="l" assignNames="length" />
4118
+ `,
4119
+ },
4120
+ "*",
4121
+ );
4122
+ });
4123
+
4124
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load
4125
+
4126
+ cy.window().then(async (win) => {
4127
+ let stateVariables = await win.returnAllStateVariables1();
4128
+ expect(
4129
+ me
4130
+ .fromAst(stateVariables["/l"].stateValues.length)
4131
+ .equals(me.fromText("sqrt((x-u)^2+(y-v)^2)")),
4132
+ ).eq(true);
4133
+ });
4134
+ });
4135
+
4136
+ it("label positioning", () => {
4137
+ cy.window().then(async (win) => {
4138
+ win.postMessage(
4139
+ {
4140
+ doenetML: `
4141
+ <text>a</text>
4142
+
4143
+ <graph name="g">
4144
+ <lineSegment endPoints="(1,2) (3,4)" labelPosition="$labelPos" name="ls">
4145
+ <label>$label</label>
4146
+ </lineSegment>
4147
+ </graph>
4148
+
4149
+ <p>label: <textinput name="label" prefill="line segment" /></p>
4150
+ <p>position:
4151
+ <choiceinput inline preselectChoice="1" name="labelPos">
4152
+ <choice>upperRight</choice>
4153
+ <choice>upperLeft</choice>
4154
+ <choice>lowerRight</choice>
4155
+ <choice>lowerLeft</choice>
4156
+ </choiceinput>
4157
+ </p>
4158
+
4159
+ <p name="pPos">Position: $ls.labelPosition</p>
4160
+ <p name="pLabel">Label: $ls.label</p>
4161
+
4162
+ `,
4163
+ },
4164
+ "*",
4165
+ );
4166
+ });
4167
+
4168
+ cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load
4169
+
4170
+ // not sure what to test as don't know how to check renderer...
4171
+
4172
+ cy.get(cesc("#\\/pPos")).should("have.text", "Position: upperright");
4173
+ cy.get(cesc("#\\/pLabel")).should("contain.text", "Label: line segment");
4174
+
4175
+ cy.get(cesc("#\\/label_input")).clear().type("nothing{enter}");
4176
+ cy.get(cesc("#\\/pLabel")).should("contain.text", "Label: nothing");
4177
+
4178
+ cy.get(cesc("#\\/labelPos")).select("upperLeft");
4179
+ cy.get(cesc("#\\/pPos")).should("have.text", "Position: upperleft");
4180
+ cy.get(cesc("#\\/labelPos")).select("lowerRight");
4181
+ cy.get(cesc("#\\/pPos")).should("have.text", "Position: lowerright");
4182
+ cy.get(cesc("#\\/labelPos")).select("lowerLeft");
4183
+ cy.get(cesc("#\\/pPos")).should("have.text", "Position: lowerleft");
4184
+ });
4185
+
4186
+ it("draggable, endpoints draggable", () => {
4187
+ cy.window().then(async (win) => {
4188
+ win.postMessage(
4189
+ {
4190
+ doenetML: `
4191
+ <graph>
4192
+ <linesegment endpoints="(1,3) (5,7)" name="p" draggable="$draggable" endpointsDraggable="$endpointsDraggable" />
4193
+ </graph>
4194
+ <p>To wait: <booleaninput name="bi" /> <boolean copySource="bi" name="bi2" /></p>
4195
+ <p>draggable: <booleaninput name="draggable" /> <boolean copySource="p.draggable" name="d2" /></p>
4196
+ <p>endpoints draggable: <booleaninput name="endpointsDraggable" /> <boolean copySource="p.endpointsDraggable" name="ed2" /></p>
4197
+ <p name="pendpt">all endpoints: $p.endpoints</p>
4198
+ `,
4199
+ },
4200
+ "*",
4201
+ );
4202
+ });
4203
+
4204
+ cy.get(cesc("#\\/d2")).should("have.text", "false");
4205
+ cy.get(cesc("#\\/ed2")).should("have.text", "false");
4206
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4207
+ .eq(0)
4208
+ .should("have.text", "(1,3)");
4209
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4210
+ .eq(2)
4211
+ .should("have.text", "(5,7)");
4212
+
4213
+ cy.window().then(async (win) => {
4214
+ let stateVariables = await win.returnAllStateVariables1();
4215
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([1, 3]);
4216
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([5, 7]);
4217
+ expect(stateVariables["/p"].stateValues.draggable).eq(false);
4218
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(false);
4219
+ });
4220
+
4221
+ cy.log("cannot move single endpoint");
4222
+ cy.window().then(async (win) => {
4223
+ await win.callAction1({
4224
+ actionName: "moveLineSegment",
4225
+ componentName: "/p",
4226
+ args: {
4227
+ point1coords: [4, 7],
4228
+ },
4229
+ });
4230
+ });
4231
+
4232
+ // wait for core to process click
4233
+ cy.get(cesc("#\\/bi")).click();
4234
+ cy.get(cesc("#\\/bi2")).should("have.text", "true");
4235
+
4236
+ cy.get(cesc("#\\/d2")).should("have.text", "false");
4237
+ cy.get(cesc("#\\/ed2")).should("have.text", "false");
4238
+
4239
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4240
+ .eq(0)
4241
+ .should("have.text", "(1,3)");
4242
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4243
+ .eq(2)
4244
+ .should("have.text", "(5,7)");
4245
+
4246
+ cy.window().then(async (win) => {
4247
+ let stateVariables = await win.returnAllStateVariables1();
4248
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([1, 3]);
4249
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([5, 7]);
4250
+ expect(stateVariables["/p"].stateValues.draggable).eq(false);
4251
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(false);
4252
+ });
4253
+
4254
+ cy.window().then(async (win) => {
4255
+ await win.callAction1({
4256
+ actionName: "moveLineSegment",
4257
+ componentName: "/p",
4258
+ args: {
4259
+ point2coords: [4, 7],
4260
+ },
4261
+ });
4262
+ });
4263
+
4264
+ // wait for core to process click
4265
+ cy.get(cesc("#\\/bi")).click();
4266
+ cy.get(cesc("#\\/bi2")).should("have.text", "false");
4267
+
4268
+ cy.get(cesc("#\\/d2")).should("have.text", "false");
4269
+ cy.get(cesc("#\\/ed2")).should("have.text", "false");
4270
+
4271
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4272
+ .eq(0)
4273
+ .should("have.text", "(1,3)");
4274
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4275
+ .eq(2)
4276
+ .should("have.text", "(5,7)");
4277
+
4278
+ cy.window().then(async (win) => {
4279
+ let stateVariables = await win.returnAllStateVariables1();
4280
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([1, 3]);
4281
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([5, 7]);
4282
+ expect(stateVariables["/p"].stateValues.draggable).eq(false);
4283
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(false);
4284
+ });
4285
+
4286
+ cy.log("cannot move both endpoints");
4287
+ cy.window().then(async (win) => {
4288
+ await win.callAction1({
4289
+ actionName: "moveLineSegment",
4290
+ componentName: "/p",
4291
+ args: {
4292
+ point1coords: [4, 7],
4293
+ point2coords: [8, 10],
4294
+ },
4295
+ });
4296
+ });
4297
+
4298
+ // wait for core to process click
4299
+ cy.get(cesc("#\\/bi")).click();
4300
+ cy.get(cesc("#\\/bi2")).should("have.text", "true");
4301
+
4302
+ cy.get(cesc("#\\/d2")).should("have.text", "false");
4303
+ cy.get(cesc("#\\/ed2")).should("have.text", "false");
4304
+
4305
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4306
+ .eq(0)
4307
+ .should("have.text", "(1,3)");
4308
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4309
+ .eq(2)
4310
+ .should("have.text", "(5,7)");
4311
+
4312
+ cy.window().then(async (win) => {
4313
+ let stateVariables = await win.returnAllStateVariables1();
4314
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([1, 3]);
4315
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([5, 7]);
4316
+ expect(stateVariables["/p"].stateValues.draggable).eq(false);
4317
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(false);
4318
+ });
4319
+
4320
+ cy.log("only endpoints draggable");
4321
+
4322
+ cy.get(cesc("#\\/endpointsDraggable")).click();
4323
+ cy.get(cesc("#\\/ed2")).should("have.text", "true");
4324
+
4325
+ cy.log("can move single endpoint");
4326
+ cy.window().then(async (win) => {
4327
+ await win.callAction1({
4328
+ actionName: "moveLineSegment",
4329
+ componentName: "/p",
4330
+ args: {
4331
+ point1coords: [4, 7],
4332
+ },
4333
+ });
4334
+ });
4335
+
4336
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow").should("contain.text", "(4,7)");
4337
+
4338
+ cy.get(cesc("#\\/d2")).should("have.text", "false");
4339
+ cy.get(cesc("#\\/ed2")).should("have.text", "true");
4340
+
4341
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4342
+ .eq(0)
4343
+ .should("have.text", "(4,7)");
4344
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4345
+ .eq(2)
4346
+ .should("have.text", "(5,7)");
4347
+
4348
+ cy.window().then(async (win) => {
4349
+ let stateVariables = await win.returnAllStateVariables1();
4350
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([4, 7]);
4351
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([5, 7]);
4352
+ expect(stateVariables["/p"].stateValues.draggable).eq(false);
4353
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(true);
4354
+ });
4355
+
4356
+ cy.log("cannot move both endpoints");
4357
+ cy.window().then(async (win) => {
4358
+ await win.callAction1({
4359
+ actionName: "moveLineSegment",
4360
+ componentName: "/p",
4361
+ args: {
4362
+ pointCoords: [
4363
+ [3, 8],
4364
+ [8, 10],
4365
+ [1, 9],
4366
+ ],
4367
+ },
4368
+ });
4369
+ });
4370
+
4371
+ // wait for core to process click
4372
+ cy.get(cesc("#\\/bi")).click();
4373
+ cy.get(cesc("#\\/bi2")).should("have.text", "false");
4374
+
4375
+ cy.get(cesc("#\\/d2")).should("have.text", "false");
4376
+ cy.get(cesc("#\\/ed2")).should("have.text", "true");
4377
+
4378
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4379
+ .eq(0)
4380
+ .should("have.text", "(4,7)");
4381
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4382
+ .eq(2)
4383
+ .should("have.text", "(5,7)");
4384
+
4385
+ cy.window().then(async (win) => {
4386
+ let stateVariables = await win.returnAllStateVariables1();
4387
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([4, 7]);
4388
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([5, 7]);
4389
+ expect(stateVariables["/p"].stateValues.draggable).eq(false);
4390
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(true);
4391
+ });
4392
+
4393
+ cy.log("endpoints and line segment draggable");
4394
+
4395
+ cy.get(cesc("#\\/draggable")).click();
4396
+ cy.get(cesc("#\\/d2")).should("have.text", "true");
4397
+
4398
+ cy.log("can move first endpoint");
4399
+ cy.window().then(async (win) => {
4400
+ await win.callAction1({
4401
+ actionName: "moveLineSegment",
4402
+ componentName: "/p",
4403
+ args: {
4404
+ point1coords: [-3, 2],
4405
+ },
4406
+ });
4407
+ });
4408
+
4409
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow").should("contain.text", "(−3,2)");
4410
+
4411
+ cy.get(cesc("#\\/d2")).should("have.text", "true");
4412
+ cy.get(cesc("#\\/ed2")).should("have.text", "true");
4413
+
4414
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4415
+ .eq(0)
4416
+ .should("have.text", "(−3,2)");
4417
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4418
+ .eq(2)
4419
+ .should("have.text", "(5,7)");
4420
+
4421
+ cy.window().then(async (win) => {
4422
+ let stateVariables = await win.returnAllStateVariables1();
4423
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([-3, 2]);
4424
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([5, 7]);
4425
+ expect(stateVariables["/p"].stateValues.draggable).eq(true);
4426
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(true);
4427
+ });
4428
+
4429
+ cy.log("can move second endpoint");
4430
+ cy.window().then(async (win) => {
4431
+ await win.callAction1({
4432
+ actionName: "moveLineSegment",
4433
+ componentName: "/p",
4434
+ args: {
4435
+ point2coords: [-9, 0],
4436
+ },
4437
+ });
4438
+ });
4439
+
4440
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow").should("contain.text", "(−9,0)");
4441
+
4442
+ cy.get(cesc("#\\/d2")).should("have.text", "true");
4443
+ cy.get(cesc("#\\/ed2")).should("have.text", "true");
4444
+
4445
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4446
+ .eq(0)
4447
+ .should("have.text", "(−3,2)");
4448
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4449
+ .eq(2)
4450
+ .should("have.text", "(−9,0)");
4451
+
4452
+ cy.window().then(async (win) => {
4453
+ let stateVariables = await win.returnAllStateVariables1();
4454
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([-3, 2]);
4455
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([-9, 0]);
4456
+ expect(stateVariables["/p"].stateValues.draggable).eq(true);
4457
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(true);
4458
+ });
4459
+
4460
+ cy.log("can move both endpoints");
4461
+ cy.window().then(async (win) => {
4462
+ await win.callAction1({
4463
+ actionName: "moveLineSegment",
4464
+ componentName: "/p",
4465
+ args: {
4466
+ point1coords: [3, 8],
4467
+ point2coords: [8, 10],
4468
+ },
4469
+ });
4470
+ });
4471
+
4472
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow").should("contain.text", "(3,8)");
4473
+
4474
+ cy.get(cesc("#\\/d2")).should("have.text", "true");
4475
+ cy.get(cesc("#\\/ed2")).should("have.text", "true");
4476
+
4477
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4478
+ .eq(0)
4479
+ .should("have.text", "(3,8)");
4480
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4481
+ .eq(2)
4482
+ .should("have.text", "(8,10)");
4483
+
4484
+ cy.window().then(async (win) => {
4485
+ let stateVariables = await win.returnAllStateVariables1();
4486
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([3, 8]);
4487
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([8, 10]);
4488
+ expect(stateVariables["/p"].stateValues.draggable).eq(true);
4489
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(true);
4490
+ });
4491
+
4492
+ cy.log("polygon but not endpoints draggable");
4493
+
4494
+ cy.get(cesc("#\\/endpointsDraggable")).click();
4495
+ cy.get(cesc("#\\/ed2")).should("have.text", "false");
4496
+
4497
+ cy.log("cannot move first endpoint");
4498
+ cy.window().then(async (win) => {
4499
+ await win.callAction1({
4500
+ actionName: "moveLineSegment",
4501
+ componentName: "/p",
4502
+ args: {
4503
+ point1coords: [9, 3],
4504
+ },
4505
+ });
4506
+ });
4507
+
4508
+ // wait for core to process click
4509
+ cy.get(cesc("#\\/bi")).click();
4510
+ cy.get(cesc("#\\/bi2")).should("have.text", "true");
4511
+
4512
+ cy.get(cesc("#\\/d2")).should("have.text", "true");
4513
+ cy.get(cesc("#\\/ed2")).should("have.text", "false");
4514
+
4515
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4516
+ .eq(0)
4517
+ .should("have.text", "(3,8)");
4518
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4519
+ .eq(2)
4520
+ .should("have.text", "(8,10)");
4521
+
4522
+ cy.window().then(async (win) => {
4523
+ let stateVariables = await win.returnAllStateVariables1();
4524
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([3, 8]);
4525
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([8, 10]);
4526
+ expect(stateVariables["/p"].stateValues.draggable).eq(true);
4527
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(false);
4528
+ });
4529
+
4530
+ cy.log("cannot move second endpoint");
4531
+ cy.window().then(async (win) => {
4532
+ await win.callAction1({
4533
+ actionName: "moveLineSegment",
4534
+ componentName: "/p",
4535
+ args: {
4536
+ point2coords: [9, 3],
4537
+ },
4538
+ });
4539
+ });
4540
+
4541
+ // wait for core to process click
4542
+ cy.get(cesc("#\\/bi")).click();
4543
+ cy.get(cesc("#\\/bi2")).should("have.text", "false");
4544
+
4545
+ cy.get(cesc("#\\/d2")).should("have.text", "true");
4546
+ cy.get(cesc("#\\/ed2")).should("have.text", "false");
4547
+
4548
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4549
+ .eq(0)
4550
+ .should("have.text", "(3,8)");
4551
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4552
+ .eq(2)
4553
+ .should("have.text", "(8,10)");
4554
+
4555
+ cy.window().then(async (win) => {
4556
+ let stateVariables = await win.returnAllStateVariables1();
4557
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([3, 8]);
4558
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([8, 10]);
4559
+ expect(stateVariables["/p"].stateValues.draggable).eq(true);
4560
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(false);
4561
+ });
4562
+
4563
+ cy.log("can move both endpoints");
4564
+ cy.window().then(async (win) => {
4565
+ await win.callAction1({
4566
+ actionName: "moveLineSegment",
4567
+ componentName: "/p",
4568
+ args: {
4569
+ point1coords: [-4, 1],
4570
+ point2coords: [9, -4],
4571
+ },
4572
+ });
4573
+ });
4574
+
4575
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow").should("contain.text", "(−4,1)");
4576
+
4577
+ cy.get(cesc("#\\/d2")).should("have.text", "true");
4578
+ cy.get(cesc("#\\/ed2")).should("have.text", "false");
4579
+
4580
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4581
+ .eq(0)
4582
+ .should("have.text", "(−4,1)");
4583
+ cy.get(cesc("#\\/pendpt") + " .mjx-mrow")
4584
+ .eq(2)
4585
+ .should("have.text", "(9,−4)");
4586
+
4587
+ cy.window().then(async (win) => {
4588
+ let stateVariables = await win.returnAllStateVariables1();
4589
+ expect(stateVariables["/p"].stateValues.endpoints[0]).eqls([-4, 1]);
4590
+ expect(stateVariables["/p"].stateValues.endpoints[1]).eqls([9, -4]);
4591
+ expect(stateVariables["/p"].stateValues.draggable).eq(true);
4592
+ expect(stateVariables["/p"].stateValues.endpointsDraggable).eq(false);
4593
+ });
4594
+ });
4595
+
4596
+ it("style description changes with theme", () => {
4597
+ cy.window().then(async (win) => {
4598
+ win.postMessage(
4599
+ {
4600
+ doenetML: `
4601
+ <setup>
4602
+ <styleDefinitions>
4603
+ <styleDefinition styleNumber="1" lineColor="brown" lineColorDarkMode="yellow" />
4604
+ <styleDefinition styleNumber="2" lineColor="#540907" lineColorWord="dark red" lineColorDarkMode="#f0c6c5" lineColorWordDarkMode="light red" />
4605
+ </styleDefinitions>
4606
+ </setup>
4607
+ <graph>
4608
+ <linesegment name="A" styleNumber="1" labelIsName endpoints="(0,0) (1,2)" />
4609
+ <linesegment name="B" styleNumber="2" labelIsName endpoints="(2,2) (3,4)" />
4610
+ <linesegment name="C" styleNumber="5" labelIsName endpoints="(4,4) (5,6)" />
4611
+ </graph>
4612
+ <p name="Adescrip">Line segment A is $A.styleDescription.</p>
4613
+ <p name="Bdescrip">B is a $B.styleDescriptionWithNoun.</p>
4614
+ <p name="Cdescrip">C is a $C.styleDescriptionWithNoun.</p>
4615
+ `,
4616
+ },
4617
+ "*",
4618
+ );
4619
+ });
4620
+
4621
+ cy.get(cesc("#\\/Adescrip")).should(
4622
+ "have.text",
4623
+ "Line segment A is thick brown.",
4624
+ );
4625
+ cy.get(cesc("#\\/Bdescrip")).should(
4626
+ "have.text",
4627
+ "B is a dark red line segment.",
4628
+ );
4629
+ cy.get(cesc("#\\/Cdescrip")).should(
4630
+ "have.text",
4631
+ "C is a thin black line segment.",
4632
+ );
4633
+
4634
+ cy.log("set dark mode");
4635
+ cy.get("#testRunner_toggleControls").click();
4636
+ cy.get("#testRunner_darkmode").click();
4637
+ cy.wait(100);
4638
+ cy.get("#testRunner_toggleControls").click();
4639
+
4640
+ cy.get(cesc("#\\/Adescrip")).should(
4641
+ "have.text",
4642
+ "Line segment A is thick yellow.",
4643
+ );
4644
+ cy.get(cesc("#\\/Bdescrip")).should(
4645
+ "have.text",
4646
+ "B is a light red line segment.",
4647
+ );
4648
+ cy.get(cesc("#\\/Cdescrip")).should(
4649
+ "have.text",
4650
+ "C is a thin white line segment.",
4651
+ );
4652
+ });
4653
+
4654
+ it("line segment based on two endpoints, one constrained to grid", () => {
4655
+ cy.window().then(async (win) => {
4656
+ win.postMessage(
4657
+ {
4658
+ doenetML: `
4659
+ <text>a</text>
4660
+ <graph>
4661
+ <point name="P" labelIsName>(3,5)
4662
+ <constraints><constrainToGrid dx="2" dy="3" /></constraints>
4663
+ </point>
4664
+ <point name="Q" labelIsName>(-4,-1)</point>
4665
+ <lineSegment endpoints="$P $Q" />
4666
+ </graph>
4667
+ <copy target="P" assignNames="Pa" />
4668
+ <copy target="Q" assignNames="Qa" />
4669
+ `,
4670
+ },
4671
+ "*",
4672
+ );
4673
+ });
4674
+
4675
+ cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load
4676
+
4677
+ let x1 = 4,
4678
+ y1 = 6;
4679
+ let x2 = -4,
4680
+ y2 = -1;
4681
+
4682
+ cy.get(cesc2("#/Pa") + " .mjx-mrow").should(
4683
+ "contain.text",
4684
+ `(${nInDOM(x1)},${nInDOM(y1)})`,
4685
+ );
4686
+ cy.get(cesc2("#/Qa") + " .mjx-mrow").should(
4687
+ "contain.text",
4688
+ `(${nInDOM(x2)},${nInDOM(y2)})`,
4689
+ );
4690
+
4691
+ cy.window().then(async (win) => {
4692
+ let stateVariables = await win.returnAllStateVariables1();
4693
+ expect(stateVariables["/P"].stateValues.xs[0]).eq(x1);
4694
+ expect(stateVariables["/P"].stateValues.xs[1]).eq(y1);
4695
+ expect(stateVariables["/P"].stateValues.coords).eqls(["vector", x1, y1]);
4696
+ expect(stateVariables["/Q"].stateValues.xs[0]).eq(x2);
4697
+ expect(stateVariables["/Q"].stateValues.xs[1]).eq(y2);
4698
+ expect(stateVariables["/Q"].stateValues.coords).eqls(["vector", x2, y2]);
4699
+ });
4700
+
4701
+ cy.log(
4702
+ "move line down 4 and right 0.5 actually moves it down 3 and right none",
4703
+ );
4704
+ cy.window().then(async (win) => {
4705
+ let dx = 0.5,
4706
+ dy = -4;
4707
+
4708
+ let x1Desired = x1 + dx;
4709
+ let y1Desired = y1 + dy;
4710
+ let x2Desired = x2 + dx;
4711
+ let y2Desired = y2 + dy;
4712
+
4713
+ dx = 0;
4714
+ dy = -3;
4715
+ x1 += dx;
4716
+ y1 += dy;
4717
+ x2 += dx;
4718
+ y2 += dy;
4719
+
4720
+ win.callAction1({
4721
+ actionName: "moveLineSegment",
4722
+ componentName: "/_linesegment1",
4723
+ args: {
4724
+ point1coords: [x1Desired, y1Desired],
4725
+ point2coords: [x2Desired, y2Desired],
4726
+ },
4727
+ });
4728
+
4729
+ cy.get(cesc2("#/Pa") + " .mjx-mrow").should(
4730
+ "contain.text",
4731
+ `(${nInDOM(x1)},${nInDOM(y1)})`,
4732
+ );
4733
+ cy.get(cesc2("#/Qa") + " .mjx-mrow").should(
4734
+ "contain.text",
4735
+ `(${nInDOM(x2)},${nInDOM(y2)})`,
4736
+ );
4737
+ });
4738
+
4739
+ cy.window().then(async (win) => {
4740
+ let stateVariables = await win.returnAllStateVariables1();
4741
+ expect(stateVariables["/P"].stateValues.xs[0]).eq(x1);
4742
+ expect(stateVariables["/P"].stateValues.xs[1]).eq(y1);
4743
+ expect(stateVariables["/P"].stateValues.coords).eqls(["vector", x1, y1]);
4744
+ expect(stateVariables["/Q"].stateValues.xs[0]).eq(x2);
4745
+ expect(stateVariables["/Q"].stateValues.xs[1]).eq(y2);
4746
+ expect(stateVariables["/Q"].stateValues.coords).eqls(["vector", x2, y2]);
4747
+ });
4748
+ });
4749
+ });