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