From 0ac75666802987acf34584a22092b5e9c204a803 Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Fri, 17 Jan 2025 11:27:18 -0600 Subject: [PATCH] remove multipage activity feature (#277) * remove multipage activity feature * remove apiURLs; support only postMessages * add `render` flag to DoenetML * send `allPossibleVariants` message after initializing * fix mathjax configuration file for version 3 --- .gitignore | 1 + package-lock.json | 43 +- packages/doenetml-iframe/package.json | 2 +- .../src/iframe-viewer-index.ts | 30 - packages/doenetml-iframe/src/index.tsx | 19 - packages/doenetml-worker/src/Core.js | 461 +---- packages/doenetml-worker/src/CoreWorker.js | 14 + packages/doenetml-worker/src/Dependencies.js | 25 - .../src/test/utils/test-core.ts | 1 - .../src/test/variants/uniqueVariants.test.ts | 7 +- packages/doenetml/package.json | 3 +- .../src/EditorViewer/EditorViewer.tsx | 16 +- .../doenetml/src/Viewer/ActivityViewer.tsx | 1797 ---------------- packages/doenetml/src/Viewer/PageViewer.jsx | 302 +-- .../src/Viewer/renderers/codeEditor-ts.tsx | 1 + .../src/Viewer/renderers/codeViewer.jsx | 1 + .../doenetml/src/Viewer/renderers/image.jsx | 11 +- packages/doenetml/src/doenetml.tsx | 73 +- packages/doenetml/src/index.ts | 6 - packages/doenetml/src/utils/activityUtils.js | 1116 ---------- .../doenetml/src/utils/activtyWebWorker.js | 27 - packages/doenetml/src/utils/pageUtils.js | 48 + .../doenetml/src/utils/prerenderWorker.js | 267 --- packages/standalone/package.json | 2 +- .../e2e/ActivityViewer/activityVariants.cy.js | 1817 ----------------- .../e2e/ActivityViewer/compiledActivity.cy.js | 78 - .../relationshipsAmongPages.cy.js | 775 ------- .../e2e/PageViewer/pageViewerAttributes.cy.js | 62 + .../e2e/dynamicalsystem/cobwebpolyline.cy.js | 303 +-- .../e2e/tagSpecific/animatefromsequence.cy.js | 210 +- .../cypress/e2e/tagSpecific/answer.cy.js | 177 +- .../e2e/tagSpecific/booleaninput.cy.js | 8 +- .../cypress/e2e/tagSpecific/circle.cy.js | 8 +- .../cypress/e2e/tagSpecific/codeeditor.cy.js | 120 +- .../e2e/tagSpecific/contentBrowser.cy.js | 8 +- .../cypress/e2e/tagSpecific/line.cy.js | 35 +- .../cypress/e2e/tagSpecific/math.cy.js | 219 +- .../cypress/e2e/tagSpecific/mathdisplay.cy.js | 223 +- .../cypress/e2e/tagSpecific/mathinput.cy.js | 48 +- .../cypress/e2e/tagSpecific/matrixinput.cy.js | 18 +- .../cypress/e2e/tagSpecific/module.cy.js | 496 +---- .../cypress/e2e/tagSpecific/point.cy.js | 20 +- .../cypress/e2e/tagSpecific/sectioning.cy.js | 105 +- .../e2e/tagSpecific/selectfromsequence.cy.js | 14 +- .../cypress/e2e/tagSpecific/slider.cy.js | 6 +- .../cypress/e2e/tagSpecific/spreadsheet.cy.js | 300 +-- .../cypress/e2e/tagSpecific/text.cy.js | 111 +- packages/test-cypress/src/CypressTest.tsx | 73 +- packages/test-viewer/src/test/testViewer.tsx | 16 +- packages/utils/src/index.ts | 1 - packages/utils/src/math/math.ts | 36 +- packages/utils/src/media/retrieveMedia.ts | 106 - 52 files changed, 988 insertions(+), 8678 deletions(-) delete mode 100644 packages/doenetml/src/Viewer/ActivityViewer.tsx delete mode 100644 packages/doenetml/src/utils/activityUtils.js delete mode 100644 packages/doenetml/src/utils/activtyWebWorker.js create mode 100644 packages/doenetml/src/utils/pageUtils.js delete mode 100644 packages/doenetml/src/utils/prerenderWorker.js delete mode 100644 packages/test-cypress/cypress/e2e/ActivityViewer/activityVariants.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/ActivityViewer/compiledActivity.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js create mode 100644 packages/test-cypress/cypress/e2e/PageViewer/pageViewerAttributes.cy.js delete mode 100644 packages/utils/src/media/retrieveMedia.ts diff --git a/.gitignore b/.gitignore index f0dcf1251..355312343 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ src/test/testCode.doenet **/cypress/videos **/cypress/screenshots +**/cypress/downloads runner-results parallel-weights.json diff --git a/package-lock.json b/package-lock.json index 1032bfbc9..21d19bf71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6057,7 +6057,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/at-least-node": { "version": "1.0.0", @@ -6150,15 +6151,6 @@ "dev": true, "license": "MIT" }, - "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, "node_modules/b4a": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", @@ -7495,6 +7487,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -9058,6 +9051,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -10428,25 +10422,6 @@ "node": ">=10" } }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -10507,6 +10482,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -14954,6 +14930,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -14962,6 +14939,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -22819,7 +22797,7 @@ }, "packages/doenetml": { "name": "@doenet/doenetml", - "version": "0.7.0-alpha21", + "version": "0.7.0-alpha23", "license": "AGPL-3.0-or-later", "dependencies": { "@chakra-ui/icons": "^2.0.19", @@ -22829,7 +22807,6 @@ "@fortawesome/free-solid-svg-icons": "^6.5.2", "@fortawesome/react-fontawesome": "^0.2.2", "@handsontable/react": "^12.4.0", - "axios": "^0.27.2", "better-react-mathjax": "^2.0.3", "copy-to-clipboard": "^3.3.3", "crypto-js": "^4.2.0", @@ -22861,7 +22838,7 @@ }, "packages/doenetml-iframe": { "name": "@doenet/doenetml-iframe", - "version": "0.7.0-alpha21", + "version": "0.7.0-alpha23", "license": "AGPL-3.0-or-later", "devDependencies": {}, "peerDependencies": { @@ -22939,7 +22916,7 @@ }, "packages/standalone": { "name": "@doenet/standalone", - "version": "0.7.0-alpha21", + "version": "0.7.0-alpha23", "license": "AGPL-3.0-or-later", "devDependencies": {} }, diff --git a/packages/doenetml-iframe/package.json b/packages/doenetml-iframe/package.json index 36cdd381d..4328b09aa 100644 --- a/packages/doenetml-iframe/package.json +++ b/packages/doenetml-iframe/package.json @@ -2,7 +2,7 @@ "name": "@doenet/doenetml-iframe", "type": "module", "description": "A renderer for DoenetML contained in an iframe", - "version": "0.7.0-alpha21", + "version": "0.7.0-alpha23", "license": "AGPL-3.0-or-later", "homepage": "https://github.com/Doenet/DoenetML#readme", "private": true, diff --git a/packages/doenetml-iframe/src/iframe-viewer-index.ts b/packages/doenetml-iframe/src/iframe-viewer-index.ts index 68c55da72..83f127486 100644 --- a/packages/doenetml-iframe/src/iframe-viewer-index.ts +++ b/packages/doenetml-iframe/src/iframe-viewer-index.ts @@ -30,42 +30,12 @@ document.addEventListener("DOMContentLoaded", () => { args, }); }, - updateActivityStatusCallback: (args: unknown) => { - messageParentFromViewer({ - callback: "updateActivityStatusCallback", - args, - }); - }, updateAttemptNumber: (args: unknown) => { messageParentFromViewer({ callback: "updateAttemptNumber", args, }); }, - pageChangedCallback: (args: unknown) => { - messageParentFromViewer({ - callback: "pageChangedCallback", - args, - }); - }, - cidChangedCallback: (args: unknown) => { - messageParentFromViewer({ - callback: "cidChangedCallback", - args, - }); - }, - checkIfCidChanged: (args: unknown) => { - messageParentFromViewer({ - callback: "checkIfCidChanged", - args, - }); - }, - setActivityAsCompleted: (args: unknown) => { - messageParentFromViewer({ - callback: "setActivityAsCompleted", - args, - }); - }, setIsInErrorState: (args: unknown) => { messageParentFromViewer({ callback: "setIsInErrorState", diff --git a/packages/doenetml-iframe/src/index.tsx b/packages/doenetml-iframe/src/index.tsx index c8d0b757c..49d8984a8 100644 --- a/packages/doenetml-iframe/src/index.tsx +++ b/packages/doenetml-iframe/src/index.tsx @@ -169,28 +169,9 @@ export function DoenetViewer({ data.args, ); } - case "updateActivityStatusCallback": { - return doenetViewerProps.updateActivityStatusCallback?.( - data.args, - ); - } case "updateAttemptNumber": { return doenetViewerProps.updateAttemptNumber?.(data.args); } - case "pageChangedCallback": { - return doenetViewerProps.pageChangedCallback?.(data.args); - } - case "cidChangedCallback": { - return doenetViewerProps.cidChangedCallback?.(data.args); - } - case "checkIfCidChanged": { - return doenetViewerProps.checkIfCidChanged?.(data.args); - } - case "setActivityAsCompleted": { - return doenetViewerProps.setActivityAsCompleted?.( - data.args, - ); - } case "setIsInErrorState": { return doenetViewerProps.setIsInErrorState?.(data.args); } diff --git a/packages/doenetml-worker/src/Core.js b/packages/doenetml-worker/src/Core.js index 6e447020c..314d20310 100644 --- a/packages/doenetml-worker/src/Core.js +++ b/packages/doenetml-worker/src/Core.js @@ -38,8 +38,7 @@ import { returnDefaultGetArrayKeysFromVarName, } from "./utils/stateVariables"; import { nanoid } from "nanoid"; -import { get as idb_get, set as idb_set } from "idb-keyval"; -import axios from "axios"; +import { set as idb_set } from "idb-keyval"; // string to componentClass: this.componentInfoObjects.allComponentClasses["string"] // componentClass to string: componentClass.componentType @@ -55,37 +54,30 @@ export default class Core { preliminaryWarnings, activityId, cid, - cidForActivity: activityCid, pageNumber, attemptNumber = 1, itemNumber = 1, serverSaveId, - activityVariantIndex, requestedVariant, requestedVariantIndex, - previousComponentTypeCounts = {}, theme, prerender = false, stateVariableChanges: stateVariableChangesString, coreId, updateDataOnContentChange, - apiURLs = {}, }) { // console.time('core'); this.coreId = coreId; this.activityId = activityId; - this.activityCid = activityCid; this.pageNumber = pageNumber; this.attemptNumber = attemptNumber; this.itemNumber = itemNumber; - this.activityVariantIndex = activityVariantIndex; this.doenetML = doenetML; this.allDoenetMLs = allDoenetMLs; this.serializedDocument = serializedDocument; this.cid = cid; - this.apiURLs = apiURLs; this.errorWarnings = { errors: [...preliminaryErrors], @@ -105,8 +97,6 @@ export default class Core { this.componentInfoObjects = componentInfoObjects; - this.previousComponentTypeCounts = previousComponentTypeCounts; - const stateVariableChanges = stateVariableChangesString ? JSON.parse( stateVariableChangesString, @@ -467,16 +457,6 @@ export default class Core { await this.document.stateValues.scoredDescendants; // to evaluated scoredDescendants - if (!foundAnswerDescendant(this.document)) { - // if there are no scored items in document - // then treat the first view of the document as a submission - // so that will get credit for viewing the page - this.saveSubmissions({ - pageCreditAchieved: - await this.document.stateValues.creditAchieved, - }); - } - setTimeout( this.sendVisibilityChangedEvents.bind(this), this.visibilityInfo.saveDelay, @@ -11284,16 +11264,8 @@ export default class Core { let alreadySaved = false; if (recordItemSubmissions.length > 0) { - // if itemNumber is zero, it means this document wasn't given any weight, - // so don't record the submission to the attempt tables - // (the event will still get recorded) - if (this.itemNumber > 0) { - let pageCreditAchieved = - await this.document.stateValues.creditAchieved; - this.saveState(true, true); - this.saveSubmissions({ pageCreditAchieved }); - alreadySaved = true; - } + this.saveState(true, true); + alreadySaved = true; } if (!alreadySaved && !doNotSave) { clearTimeout(this.savePageStateTimeoutID); @@ -11382,11 +11354,9 @@ export default class Core { const payload = { activityId: this.activityId, - activityCid: this.activityCid, pageCid: this.cid, pageNumber: this.pageNumber, attemptNumber: this.attemptNumber, - activityVariantIndex: this.activityVariantIndex, pageVariantIndex: this.requestedVariant.index, verb: event.verb, object: JSON.stringify(event.object, serializedComponentsReplacer), @@ -11402,19 +11372,10 @@ export default class Core { version: "0.1.1", }; - if (this.apiURLs.postMessages) { - postMessage({ - messageType: "sendEvent", - data: payload, - }); - } else { - try { - let resp = await axios.post(this.apiURLs.recordEvent, payload); - // console.log(">>>>resp from record event", resp.data) - } catch (e) { - console.error(`Error saving event: ${e.message}`); - } - } + postMessage({ + messageType: "sendEvent", + data: payload, + }); } processVisibilityChangedEvent(event) { @@ -13063,323 +13024,14 @@ export default class Core { this.pageStateToBeSavedToDatabase.serverSaveId = this.serverSaveId; - if (this.apiURLs.postMessages) { - postMessage({ - messageType: "saveCreditForItem", - state: { ...this.pageStateToBeSavedToDatabase }, - score: await this.document.stateValues.creditAchieved, - }); - return; - } - - let resp; - - this.savingPageState = true; - - try { - resp = await axios.post( - this.apiURLs.savePageState, - this.pageStateToBeSavedToDatabase, - ); - } catch (e) { - postMessage({ - messageType: "sendAlert", - coreId: this.coreId, - args: { - message: `Error. Latest changes not saved. ${resp.data.message}`, - alertType: "error", - id: "dataError", - }, - }); - - this.failedToSavePageState = true; - this.savingPageState = false; - - return; - } - - this.savingPageState = false; - - if (resp.status === null) { - postMessage({ - messageType: "sendAlert", - coreId: this.coreId, - args: { - message: `Error. Latest changes not saved. Are you connected to the internet?`, - alertType: "error", - id: "dataError", - }, - }); - - this.failedToSavePageState = true; - - return; - } - - let data = resp.data; - - if (!data.success) { - postMessage({ - messageType: "sendAlert", - coreId: this.coreId, - args: { - message: `Error. Latest changes not saved. ${data.message}`, - alertType: "error", - id: "dataError", - }, - }); - - this.failedToSavePageState = true; - - return; - } - - this.failedToSavePageState = false; - - this.serverSaveId = data.saveId; - - if (this.flags.allowLocalState) { - await idb_set( - `${this.activityId}|${this.pageNumber}|${this.attemptNumber}|${this.cid}|ServerSaveId`, - data.saveId, - ); - } - - if (data.stateOverwritten) { - // if a new attempt number was generated or the cid didn't change, - // then we reset the page to the new state - if ( - this.attemptNumber !== Number(data.attemptNumber) || - this.cid === data.cid - ) { - if (this.flags.allowLocalState) { - await idb_set( - `${this.activityId}|${this.pageNumber}|${data.attemptNumber}|${data.cid}`, - { - data_format_version, - coreState: data.coreState, - rendererState: data.rendererState, - coreInfo: data.coreInfo, - saveId: data.saveId, - }, - ); - } - - postMessage({ - messageType: "resetPage", - coreId: this.coreId, - args: { - changedOnDevice: data.device, - newCid: data.cid, - newAttemptNumber: Number(data.attemptNumber), - }, - }); - } else { - // if the cid changed without the attemptNumber changing, something went wrong - postMessage({ - messageType: "inErrorState", - coreId: this.coreId, - args: { - errMsg: "Content changed unexpectedly!", - }, - }); - } - } - // TODO: send message so that UI can show changes have been synchronized - - // console.log(">>>>recordContentInteraction data",data) - } - - saveSubmissions({ pageCreditAchieved }) { - if (!this.flags.allowSaveSubmissions) { - return; - } - - if (this.apiURLs.postMessages) { - // do nothing, saving credit is combined with saving page state in the SPLICE api - // that is implemented by Runestone - return; - } - - const payload = { - activityId: this.activityId, - attemptNumber: this.attemptNumber, - credit: pageCreditAchieved, - itemNumber: this.itemNumber, - }; - - axios - .post(this.apiURLs.saveCreditForItem, payload) - .then((resp) => { - // console.log('>>>>saveCreditForItem resp', resp.data); - - if (resp.status === null) { - postMessage({ - messageType: "sendAlert", - coreId: this.coreId, - args: { - message: `Credit not saved due to error. Are you connected to the internet?`, - alertType: "error", - id: "creditDataError", - }, - }); - - this.failedToSaveCreditForItem = true; - } else if (!resp.data.success) { - postMessage({ - messageType: "sendAlert", - coreId: this.coreId, - args: { - message: resp.data.message, - alertType: "error", - id: "creditDataError", - }, - }); - - this.failedToSaveCreditForItem = true; - } else { - let data = resp.data; - - postMessage({ - messageType: "updateCreditAchieved", - coreId: this.coreId, - args: { - creditByItem: data.creditByItem.map(Number), - creditForAssignment: Number( - data.creditForAssignment, - ), - creditForAttempt: Number(data.creditForAttempt), - showCorrectness: data.showCorrectness === "1", - totalPointsOrPercent: Number( - data.totalPointsOrPercent, - ), - }, - }); - - this.failedToSaveCreditForItem = false; - } - }) - .catch((e) => { - postMessage({ - messageType: "sendAlert", - coreId: this.coreId, - args: { - message: `Credit not saved due to error: ${e.message}`, - alertType: "error", - id: "creditDataError", - }, - }); - - this.failedToSaveCreditForItem = true; - }); + postMessage({ + messageType: "saveCreditForItem", + state: { ...this.pageStateToBeSavedToDatabase }, + score: await this.document.stateValues.creditAchieved, + }); + return; } - // submitResponseCallBack(results) { - - // // console.log(`submit response callback`) - // // console.log(results); - // return; - - // if (!results.success) { - // let errorMessage = "Answer not saved due to a network error. \nEither you are offline or your authentication has timed out."; - // this.renderer.updateSection({ - // title: this.state.title, - // viewedSolution: this.state.viewedSolution, - // isError: true, - // errorMessage, - // }); - // alert(errorMessage); - - // this.coreFunctions.requestUpdate({ - // updateType: "updateRendererOnly", - // }); - // } else if (results.viewedSolution) { - // console.log(`******** Viewed solution for ${scoredComponent.componentName}`); - // this.coreFunctions.requestUpdate({ - // updateType: "updateValue", - // updateInstructions: [{ - // componentName: scoredComponent.componentName, - // variableUpdates: { - // viewedSolution: { changes: true }, - // } - // }] - // }) - // } - - // // if this.answersToSubmitCounter is a positive number - // // that means that we have call this.submitAllAnswers and we still have - // // some answers that haven't been submitted - // // In this case, we will decrement this.answersToSubmitCounter - // // If this.answersToSubmitCounter newly becomes zero, - // // then we know that we have submitted the last one answer - // if (this.answersToSubmitCounter > 0) { - // this.answersToSubmitCounter -= 1; - // if (this.answersToSubmitCounter === 0) { - // this.externalFunctions.allAnswersSubmitted(); - // } - // } - // } - - // addComponents({ serializedComponents, parent }) { - // //Check if - // //Child logic is violated - // //Parent exists - // //Check composites in serializedComponents?? - // } - - // getDeferredStateVariable({ component, stateVariable, upstreamComponent, upstreamStateVariable, dependencyValues, inverseDefinition }) { - - // // console.log(`get deferred state variable ${stateVariable} of ${component.componentName}`) - - // let inverseResult = inverseDefinition({ dependencyValues, stateValues: upstreamComponent.stateValues }); - - // if (!inverseResult.success) { - // console.warn(`Inverse definition for deferring state variable failed. component: ${component.componentName}, stateVariable: ${stateVariable}, upstreamComponent: ${upstreamComponent.componentName}, upstreamStateVariable: ${upstreamStateVariable}`); - // return undefined; - // } - - // for (let newInstruction of inverseResult.instructions) { - // if (newInstruction.setDependency) { - // let dependencyName = newInstruction.setDependency; - - // let dep = this.dependencies.downstreamDependencies[upstreamComponent.componentName][upstreamStateVariable][dependencyName]; - - // if (dep.dependencyType === "child") { - // let cName = dep.downstreamComponentNames[newInstruction.childIndex]; - // if (!cName) { - // throw Error(`Invalid inverse definition of ${stateVariable} of ${component.componentName}: ${dependencyName} child of index ${newInstruction.childIndex} does not exist.`) - // } - // let varName = dep.mappedDownstreamVariableNamesByComponent[newInstruction.childIndex][newInstruction.variableIndex]; - // if (!varName) { - // throw Error(`Invalid inverse definition of ${stateVariable} of ${component.componentName}: ${dependencyName} variable of index ${newInstruction.variableIndex} does not exist..`) - // } - - // let compNew = this._components[cName]; - - // // delete before assigning value to remove any getter for the property - // delete compNew.state[varName].value; - // delete compNew.state[varName].deferred; - // compNew.state[varName].value = newInstruction.desiredValue; - - // } else { - // throw Error(`unimplemented dependency type ${dep.dependencyType} in deferred inverse definition`) - // } - - // } else { - // throw Error(`Unrecognized instruction deferred inverse definition of ${stateVariable} of ${component.componentName}`) - // } - // } - - // // if value of state variable still has a get, then it wasn't defined - // // in the function called for its definition - // if (Object.getOwnPropertyDescriptor(component.state[stateVariable], 'value').get) { - // throw Error(`deferred inverse definition of ${stateVariable} of ${component.componentName} didn't return value of variable`); - // } - - // return component.state[stateVariable].value; - - // } - async recordSolutionView() { // TODO: check if student was actually allowed to view solution. @@ -13392,82 +13044,19 @@ export default class Core { }; } - if (this.apiURLs.postMessages) { - postMessage({ - messageType: "recordSolutionView", - activityId: this.activityId, - itemNumber: this.itemNumber, - pageNumber: this.pageNumber, - attemptNumber: this.attemptNumber, - }); - - return { - allowView: true, - message: "", - scoredComponent: this.documentName, - }; - } - - try { - const resp = await axios.post(this.apiURLs.reportSolutionViewed, { - activityId: this.activityId, - itemNumber: this.itemNumber, - pageNumber: this.pageNumber, - attemptNumber: this.attemptNumber, - }); - - if (resp.status === null) { - let message = `Cannot show solution due to error. Are you connected to the internet?`; - postMessage({ - messageType: "sendAlert", - coreId: this.coreId, - args: { - message, - alertType: "error", - id: "solutionDataError", - }, - }); - return { - allowView: false, - message, - scoredComponent: this.documentName, - }; - } else { - let data = resp.data; - if (data.success) { - return { - allowView: true, - message: "", - scoredComponent: this.documentName, - }; - } else { - let message = `Cannot show solution due to error: ${data.message}`; - return { - allowView: false, - message, - scoredComponent: this.documentName, - }; - } - } - } catch (e) { - let message = `Cannot show solution due to error.`; - - postMessage({ - messageType: "sendAlert", - coreId: this.coreId, - args: { - message, - alertType: "error", - id: "solutionDataError", - }, - }); + postMessage({ + messageType: "recordSolutionView", + activityId: this.activityId, + itemNumber: this.itemNumber, + pageNumber: this.pageNumber, + attemptNumber: this.attemptNumber, + }); - return { - allowView: false, - message, - scoredComponent: this.documentName, - }; - } + return { + allowView: true, + message: "", + scoredComponent: this.documentName, + }; } get scoredItemWeights() { diff --git a/packages/doenetml-worker/src/CoreWorker.js b/packages/doenetml-worker/src/CoreWorker.js index dbf26142b..691c031e1 100644 --- a/packages/doenetml-worker/src/CoreWorker.js +++ b/packages/doenetml-worker/src/CoreWorker.js @@ -145,6 +145,10 @@ async function initializeWorker({ messageType: "initializeResult", args: initializeResult, }); + postMessage({ + messageType: "allPossibleVariants", + args: { success: false }, + }); } coreBaseArgs = { @@ -166,6 +170,16 @@ async function initializeWorker({ messageType: "initializeResult", args: initializeResult, }); + + let allPossibleVariants = await returnAllPossibleVariants( + coreBaseArgs.serializedDocument, + coreBaseArgs.componentInfoObjects, + ); + + postMessage({ + messageType: "allPossibleVariants", + args: { success: true, allPossibleVariants }, + }); } async function createCore(args) { diff --git a/packages/doenetml-worker/src/Dependencies.js b/packages/doenetml-worker/src/Dependencies.js index 8a75de124..7d62de892 100644 --- a/packages/doenetml-worker/src/Dependencies.js +++ b/packages/doenetml-worker/src/Dependencies.js @@ -7903,31 +7903,6 @@ class CountAmongSiblingsDependency extends Dependency { .map((x) => x.componentName) .indexOf(this.upstreamComponentName) + 1; - if (this.parentName === this.dependencyHandler.core.documentName) { - let previousCounts = - this.dependencyHandler.core.previousComponentTypeCounts; - - if (this.includeInheritedComponentTypes) { - for (let cType in previousCounts) { - if ( - this.dependencyHandler.componentInfoObjects.isInheritedComponentType( - { - inheritedComponentType: cType, - baseComponentType: childComponentType, - }, - ) - ) { - value += previousCounts[cType]; - } - } - } else { - let thisPreviousCount = previousCounts[childComponentType]; - if (thisPreviousCount) { - value += thisPreviousCount; - } - } - } - // don't need changes, as it is changed directly from core // and then upstream variables are marked as changed return { value, changes: {} }; diff --git a/packages/doenetml-worker/src/test/utils/test-core.ts b/packages/doenetml-worker/src/test/utils/test-core.ts index 6b6e79b2f..7de240e16 100644 --- a/packages/doenetml-worker/src/test/utils/test-core.ts +++ b/packages/doenetml-worker/src/test/utils/test-core.ts @@ -67,7 +67,6 @@ export async function createTestCore({ componentInfoObjects, activityId: "", cid: "", - cidForActivity: "", pageNumber: 1, serverSaveId: "", activityVariantIndex: 1, diff --git a/packages/doenetml-worker/src/test/variants/uniqueVariants.test.ts b/packages/doenetml-worker/src/test/variants/uniqueVariants.test.ts index de136da39..2168bd72d 100644 --- a/packages/doenetml-worker/src/test/variants/uniqueVariants.test.ts +++ b/packages/doenetml-worker/src/test/variants/uniqueVariants.test.ts @@ -1717,8 +1717,6 @@ describe("Unique variant tests", async () => { expect(stateVariables["/n"].stateValues.value).eq(n); } - console.log({ m, n, mOptions, nOptions }); - expect( stateVariables["/_document1"].sharedParameters .allPossibleVariants, @@ -2122,10 +2120,7 @@ describe("Unique variant tests", async () => { variantsFromProblem = false, documentAndProblemVariantsDiffer = false, }: { - createDoenetML: ({ - include, - exclude, - }?: { + createDoenetML: (arg?: { include?: string[]; exclude?: string[]; }) => string; diff --git a/packages/doenetml/package.json b/packages/doenetml/package.json index 62a5764c0..eda6e7594 100644 --- a/packages/doenetml/package.json +++ b/packages/doenetml/package.json @@ -2,7 +2,7 @@ "name": "@doenet/doenetml", "type": "module", "description": "Semantic markup for building interactive web activities", - "version": "0.7.0-alpha21", + "version": "0.7.0-alpha23", "license": "AGPL-3.0-or-later", "homepage": "https://github.com/Doenet/DoenetML#readme", "private": true, @@ -68,7 +68,6 @@ "@fortawesome/free-solid-svg-icons": "^6.5.2", "@fortawesome/react-fontawesome": "^0.2.2", "@handsontable/react": "^12.4.0", - "axios": "^0.27.2", "better-react-mathjax": "^2.0.3", "copy-to-clipboard": "^3.3.3", "crypto-js": "^4.2.0", diff --git a/packages/doenetml/src/EditorViewer/EditorViewer.tsx b/packages/doenetml/src/EditorViewer/EditorViewer.tsx index 5b5051ecb..58e7cbd14 100644 --- a/packages/doenetml/src/EditorViewer/EditorViewer.tsx +++ b/packages/doenetml/src/EditorViewer/EditorViewer.tsx @@ -18,7 +18,7 @@ import { WarningTwoIcon } from "@chakra-ui/icons"; // @ts-ignore import VariantSelect from "./VariantSelect"; import { CodeMirror } from "@doenet/codemirror"; -import { ActivityViewer } from "../Viewer/ActivityViewer"; +import { PageViewer } from "../Viewer/PageViewer"; import ErrorWarningPopovers from "./ErrorWarningPopovers"; import type { WarningDescription, ErrorDescription } from "@doenet/utils"; import { nanoid } from "nanoid"; @@ -27,12 +27,10 @@ import { prettyPrint } from "@doenet/parser"; export function EditorViewer({ doenetML: initialDoenetML, activityId: specifiedActivityId, - paginate = false, location = {}, navigate, - idsIncludeActivityId = true, + prefixForIds = "", linkSettings, - addBottomPadding = false, darkMode = "light", showAnswerTitles, width = "100%", @@ -52,12 +50,10 @@ export function EditorViewer({ }: { doenetML: string; activityId?: string; - paginate?: boolean; location?: any; navigate?: any; - idsIncludeActivityId?: boolean; + prefixForIds?: string; linkSettings?: { viewURL: string; editURL: string }; - addBottomPadding?: boolean; darkMode?: "dark" | "light"; showAnswerTitles?: boolean; width?: string; @@ -477,7 +473,7 @@ export function EditorViewer({ ref={scrollableContainer} > {/* @ts-ignore */} - console.log(msg); - -export function ActivityViewer({ - doenetML: doenetMLFromProps, - updateDataOnContentChange = false, - flags, - cid: cidFromProps, - activityId: activityIdFromProps, - userId, - attemptNumber: attemptNumberFromProps, - requestedVariantIndex: requestedVariantIndexFromProps, - updateCreditAchievedCallback, - updateActivityStatusCallback, - updateAttemptNumber, - pageChangedCallback, - paginate, - showFinishButton = false, - cidChangedCallback, - checkIfCidChanged, - setActivityAsCompleted, - setIsInErrorState, - apiURLs = {}, - generatedVariantCallback, - setErrorsAndWarningsCallback, - forceDisable = false, - forceShowCorrectness = false, - forceShowSolution = false, - forceUnsuppressCheckwork = false, - location = {}, - navigate, - idsIncludeActivityId = true, - linkSettings, - addBottomPadding = true, - scrollableContainer = window, - darkMode = "light", - showAnswerTitles, -}: { - doenetML: string; - updateDataOnContentChange?: boolean; - flags: DoenetMLFlags; - cid?: string; - activityId?: string; - userId?: string; - attemptNumber?: number; - requestedVariantIndex?: number; - updateCreditAchievedCallback?: Function; - updateActivityStatusCallback?: Function; - updateAttemptNumber?: Function; - pageChangedCallback?: Function; - paginate?: boolean; - showFinishButton?: boolean; - cidChangedCallback?: Function; - checkIfCidChanged?: Function; - setActivityAsCompleted?: Function; - setIsInErrorState?: Function; - apiURLs?: any; - generatedVariantCallback?: Function; - setErrorsAndWarningsCallback?: Function; - forceDisable?: boolean; - forceShowCorrectness?: boolean; - forceShowSolution?: boolean; - forceUnsuppressCheckwork?: boolean; - location?: any; - navigate?: any; - idsIncludeActivityId?: boolean; - linkSettings?: { viewURL: string; editURL: string }; - addBottomPadding?: boolean; - scrollableContainer?: HTMLDivElement | Window; - darkMode?: "dark" | "light"; - showAnswerTitles?: boolean; -}) { - const [errMsg, setErrMsg] = useState(""); - - const [ - { - lastCidFromProps, - lastDoenetMLFromProps, - attemptNumber, - requestedVariantIndex, - }, - setInfoFromProps, - ]: [ - { - lastCidFromProps: string | null; - lastDoenetMLFromProps: string | null; - attemptNumber: number | null; - requestedVariantIndex: number | null; - }, - Function, - ] = useState({ - lastCidFromProps: null, - lastDoenetMLFromProps: null, - attemptNumber: null, - requestedVariantIndex: null, - }); - - const attemptNumberRef = useRef(null); - attemptNumberRef.current = attemptNumber; - - const [cid, setCid] = useState(""); - const cidRef = useRef(""); - cidRef.current = cid; - - const [activityId, setActivityId] = useState( - activityIdFromProps ?? "viewer-" + nanoid(5), - ); - - const doenetML = useRef(""); - - const [activityDefinition, setActivityDefinition] = useState(null); - - const [variantIndex, setVariantIndex] = useState(-1); - const variantIndexRef = useRef(-1); - variantIndexRef.current = variantIndex; - - const [stage, setStage] = useState("initial"); - let stageRef = useRef(""); - stageRef.current = stage; - - const settingUp = useRef(true); - - const [activityContentChanged, setActivityContentChanged] = useState(false); - - const [order, setOrder] = useState(null); - - const [currentPage, setCurrentPage] = useState(0); - const currentPageRef = useRef(currentPage); // so that event listener can get new current page - currentPageRef.current = currentPage; // so updates on every refresh - - const savingActivityState = useRef(false); - - const [activityAttemptNumberSetUp, setActivityAttemptNumberSetUp] = - useState(0); - - const [nPages, setNPages] = useState(0); - - const pageCoreWorkersInfo = useRef([]); - const [variantsByPage, setVariantsByPage] = useState(null); - const [itemWeights, setItemWeights] = useState([]); - const previousComponentTypeCountsByPage = useRef([]); - - const serverSaveId = useRef(null); - - const activityStateToBeSavedToDatabase = useRef({}); - const changesToBeSaved = useRef(false); - - const saveStateToDBTimerId = useRef(null); - const activityInfo = useRef(null); - const activityInfoString = useRef(""); - const pageAtPreviousSave = useRef(-1); - const pageAtPreviousSaveToDatabase = useRef(-1); - - const [pageInfo, setPageInfo] = useState<{ - pageIsVisible: boolean[]; - pageIsActive: boolean[]; - pageCoreCreated: boolean[]; - waitingForPagesCore: number | null; - }>({ - pageIsVisible: [], - pageIsActive: [], - pageCoreCreated: [], - waitingForPagesCore: null, - }); - - const [renderedPages, setRenderedPages] = useState([]); - const allPagesRendered = useRef(false); - - const nodeRef = useRef(null); - const ignoreNextScroll = useRef(false); - const stillNeedToScrollTo = useRef(null); - - let hash = location.hash; - const previousLocations = useRef>({}); - const currentLocationKey = useRef(null); - const viewerWasUnmounted = useRef(false); - - const [finishAssessmentMessageOpen, setFinishAssessmentMessageOpen] = - useState(false); - const [processingSubmitAll, setProcessingSubmitAll] = useState(false); - - const errorsAndWarningsByPage = useRef< - { errors: ErrorDescription[]; warnings: WarningDescription[] }[] - >([]); - const errorsActivitySpecific = useRef([]); - - let activityPrefix = ""; - let activityPrefixUnescaped = ""; - if (idsIncludeActivityId) { - activityPrefixUnescaped = activityId; - activityPrefix = cesc(activityId); - } - - useEffect(() => { - return () => { - saveState({ overrideThrottle: true }); - viewerWasUnmounted.current = true; - }; - }, []); - - useEffect(() => { - updateActivityStatusCallback?.({ - itemWeights, - currentPage, - activityAttemptNumberSetUp, - }); - }, [ - updateActivityStatusCallback, - itemWeights, - currentPage, - activityAttemptNumberSetUp, - ]); - - useEffect(() => { - // @ts-ignore - window.returnActivityData = function () { - return { - activityDefinition, - requestedVariantIndex, - variantIndex, - cid, - order, - currentPage, - nPages, - variantsByPage, - itemWeights, - }; - }; - }, [ - activityDefinition, - requestedVariantIndex, - variantIndex, - cid, - order, - currentPage, - nPages, - variantsByPage, - itemWeights, - ]); - - function scrollListener() { - // find page that is at the top - if (ignoreNextScroll.current) { - ignoreNextScroll.current = false; - } else { - let topPage; - for (let ind = 0; ind < nPages - 1; ind++) { - let thePage = document.getElementById( - `page${ind + 1}-${activityId}`, - ); - if (thePage) { - let { bottom } = thePage.getBoundingClientRect(); - if (bottom < 50) { - topPage = ind + 2; - } else if (!topPage) { - topPage = 1; - } - } - } - if (topPage && topPage !== currentPageRef.current) { - setCurrentPage(topPage); - } - } - } - - useEffect(() => { - // for non-paginated activity - // set the current page to be the page at the top of the screen - // will be used to set the url hash - - if (!paginate && nPages > 1) { - scrollableContainer.addEventListener("scroll", scrollListener); - } else { - scrollableContainer.removeEventListener("scroll", scrollListener); - } - }, [paginate, nPages]); - - useEffect(() => { - pageChangedCallback?.(currentPage); - }, [currentPage]); - - useEffect(() => { - if (hash && nPages) { - let match = hash.match(/^#page(\d+)/); - if (match) { - let newPage = Math.max(1, Math.min(nPages, match[1])); - if (newPage !== currentPage) { - setCurrentPage(newPage); - } - } - } - }, [hash, nPages]); - - useEffect(() => { - if (currentPage > 0 && nPages > 1) { - let hashPage = Number(hash?.match(/^#page(\d+)/)?.[1]); - if (hashPage !== currentPage) { - let pageAnchor = `#page${currentPage}`; - // if we have moved to a page that does not correspond to the hash - // modify the hash to match the page. - let navigateAttrs: { - replace: boolean; - state?: { doNotScroll: boolean }; - } = { replace: true }; - if (!paginate) { - // If not paginated, then do not scroll to the top of the page, - // as the page change could be triggered by scrolling - - navigateAttrs.state = { doNotScroll: true }; - } - navigate?.(location.search + pageAnchor, navigateAttrs); - } - if (stillNeedToScrollTo.current) { - document - .getElementById(stillNeedToScrollTo.current) - ?.scrollIntoView(); - stillNeedToScrollTo.current = null; - } - } - }, [currentPage, nPages]); - - useEffect(() => { - if ( - allPagesRendered.current && - !paginate && - hash?.match(/^#page(\d+)$/) - ) { - ignoreNextScroll.current = true; - document.getElementById(hash.slice(1))?.scrollIntoView(); - } - }, [allPagesRendered.current]); - - useEffect(() => { - // Keep track of scroll position when clicked on a link - // If navigate back to that location (i.e., hit back button) - // then scroll back to the location when clicked - - // console.log({ - // currentLocationKey: currentLocationKey.current, - // newLocationKey: location.key, - // scrollPositionFromLink: location.state?.previousScrollPosition, - // newScrollPosition: previousLocations.current[location.key]?.lastScrollPosition - // }) - - let foundNewInPrevious = false; - - if (currentLocationKey.current !== location.key) { - if ( - location.state?.previousScrollPosition !== undefined && - currentLocationKey.current - ) { - previousLocations.current[ - currentLocationKey.current - ].lastScrollPosition = location.state.previousScrollPosition; - } - - if (previousLocations.current[location.key]) { - foundNewInPrevious = true; - - if ( - previousLocations.current[location.key] - ?.lastScrollPosition !== undefined - ) { - scrollableContainer.scroll({ - top: previousLocations.current[location.key] - .lastScrollPosition, - }); - } - } - - previousLocations.current[location.key] = { ...location }; - currentLocationKey.current = location.key; - } - - stillNeedToScrollTo.current = null; - - // since the from react router doesn't seem to scroll into hashes - // always scroll to the hash the first time we get a location from a - if ( - hash && - !location.state?.doNotScroll && - (location.key === "default" || !foundNewInPrevious) - ) { - let scrollTo = hash.slice(1); - if (paginate && hash.match(/^#page(\d+)$/)) { - // if paginate, want to scroll to top of activity so can still see page controls - scrollTo = `${activityPrefix}top`; - } - if ( - paginate && - Number(hash.match(/^#page(\d+)/)?.[1]) !== currentPage - ) { - stillNeedToScrollTo.current = scrollTo; - } else { - document.getElementById(scrollTo)?.scrollIntoView(); - } - } - }, [location]); - - function resetActivity({ - changedOnDevice, - newCid, - newAttemptNumber, - }: { - changedOnDevice: boolean; - newCid: string; - newAttemptNumber: number; - }) { - console.log("resetActivity", changedOnDevice, newCid, newAttemptNumber); - - if (newAttemptNumber !== attemptNumber) { - if (updateAttemptNumber) { - sendAlert( - `Reverted activity as attempt number changed on other device`, - "info", - ); - updateAttemptNumber(newAttemptNumber); - } else { - // what do we do in this case? - setIsInErrorState?.(true); - setErrMsg( - "how to reset attempt number when not given updateAttemptNumber function?", - ); - } - } else if (newCid !== cid) { - setIsInErrorState?.(true); - setErrMsg("Content changed unexpectedly!"); - } else { - // since, at least for now, only activity state is page number, - // we ignore the change - } - - // sendAlert(`Reverted page to state saved on device ${changedOnDevice}`, "error"); - } - - async function calculateCidDefinition() { - let cid; - - if (typeof lastDoenetMLFromProps === "string" || !lastCidFromProps) { - // If we were given doenetML as a prop, we'll calculate cid from the doenetML. - // Also if were not given either doenetML or cid, then we'll calculate cid from a blank string doenetML. - - const doenetMLOrEmptyString = - typeof lastDoenetMLFromProps === "string" - ? lastDoenetMLFromProps - : ""; - cid = await cidFromText(doenetMLOrEmptyString); - - // If were given both doenetML and cid as a prop and the doenetML doesn't match the cid, - // then put in error state - if (lastCidFromProps && cid !== lastCidFromProps) { - setIsInErrorState?.(true); - setErrMsg( - `activity definition did not match specified cid: ${lastCidFromProps}`, - ); - return; - } - - doenetML.current = doenetMLOrEmptyString; - } else { - // We were given cid as a prop (but not doenetML). - // Attempt to retrieve the doenetML corresponding to the cid. - try { - doenetML.current = await retrieveTextFileForCid( - lastCidFromProps, - "doenet", - ); - } catch (e) { - setIsInErrorState?.(true); - setErrMsg( - `activity definition not found for cid: ${lastCidFromProps}`, - ); - return; - } - cid = lastCidFromProps; - } - - setCid(cid); - - // at this point, doenetML.current is set, so we parse it to get the JSON for the activity definition - let result = await parseActivityDefinition(doenetML.current, cid); - - if (result.errors.length > 0) { - let doenetMLNewlines = findAllNewlines(doenetML.current); - for (let err of result.errors) { - if (err.doenetMLrange && !("lineBegin" in err.doenetMLrange)) { - Object.assign( - err.doenetMLrange, - getLineCharRange(err.doenetMLrange, doenetMLNewlines), - ); - } - } - } - - errorsActivitySpecific.current = result.errors; - - setActivityDefinition(result.activityJSON); - setStage("continue"); - } - - async function loadState() { - let loadedState = false; - let newItemWeights; - let newVariantIndex; - let loadedFromInitialState = false; - - if (flags.allowLocalState) { - let localInfo; - - try { - localInfo = await idb_get( - `${activityId}|${attemptNumber}|${cid}`, - ); - } catch (e) { - // ignore error - } - - if (localInfo) { - if (flags.allowSaveState) { - // attempt to save local info to database, - // reseting data to that from database if it has changed since last save - - let result = - await saveLoadedLocalStateToDatabase(localInfo); - - if (result.changedOnDevice) { - if (Number(result.newAttemptNumber) !== attemptNumber) { - resetActivity({ - changedOnDevice: result.changedOnDevice, - newCid: result.newCid, - newAttemptNumber: Number( - result.newAttemptNumber, - ), - }); - return; - } else if (result.newCid !== cid) { - // if cid changes for the same attempt number, then something went wrong - setIsInErrorState?.(true); - setErrMsg(`content changed unexpectedly!`); - } - - // if just the localInfo changed, use that instead - localInfo = result.newLocalInfo; - - // no need to send sendAlert, as state is just page number - } - } - - serverSaveId.current = localInfo.saveId; - - // activityState is just currentPage - // if hash doesn't already specify a page, set page from activityState - if (!hash?.match(/^#page(\d+)/)) { - setCurrentPage(localInfo.activityState.currentPage); - } - - // activityInfo is activityPages, variantsByPage, itemWeights, and numVariants - let newActivityInfo = localInfo.activityInfo; - newVariantIndex = localInfo.variantIndex; - setVariantIndex(newVariantIndex); - setNPages(newActivityInfo.activityPages.length); - setOrder( - await normalizeLoadedOrder(newActivityInfo.activityPages), - ); - setVariantsByPage(newActivityInfo.variantsByPage); - setItemWeights(newActivityInfo.itemWeights); - newItemWeights = newActivityInfo.itemWeights; - previousComponentTypeCountsByPage.current = - newActivityInfo.previousComponentTypeCounts || []; - - activityInfo.current = newActivityInfo; - activityInfoString.current = JSON.stringify( - activityInfo.current, - ); - - let workerResult = await createAndInitializePageCoreWorkers( - newActivityInfo.activityPages, - flags, - ); - pageCoreWorkersInfo.current = workerResult.pageCoreWorkersInfo; - errorsActivitySpecific.current.push( - ...normalizeErrors(workerResult.errors, doenetML.current), - ); - - loadedState = true; - } - } - - if (!loadedState) { - // if didn't load core state from local storage, try to load from database - - // even if allowLoadState is false, - // still call loadActivityState, in which case it will only retrieve the initial activity state - - const payload = { - params: { - cid, - attemptNumber, - activityId, - userId, - allowLoadState: flags.allowLoadState, - }, - }; - - let resp; - - if (apiURLs.loadActivityState) { - try { - resp = await axios.get(apiURLs.loadActivityState, payload); - - if (!resp.data.success) { - if (flags.allowLoadState) { - setIsInErrorState?.(true); - setErrMsg( - `Error loading activity state: ${resp.data.message}`, - ); - return; - } else { - // ignore this error if didn't allow loading of page state - } - } - } catch (e: any) { - if (flags.allowLoadState) { - setIsInErrorState?.(true); - setErrMsg(`Error loading activity state: ${e.message}`); - return; - } else { - // ignore this error if didn't allow loading of page state - } - } - } - - if (resp?.data.loadedState) { - let newActivityInfo = JSON.parse(resp.data.activityInfo); - let activityState = JSON.parse(resp.data.activityState); - - // activityState is just currentPage - // if hash doesn't already specify a page, set page from activityState - if (!hash?.match(/^#page(\d+)/)) { - setCurrentPage(activityState.currentPage); - } - - // activityInfo is activityPages, variantsByPage, itemWeights, and numVariants - newVariantIndex = resp.data.variantIndex; - setVariantIndex(newVariantIndex); - setNPages(newActivityInfo.activityPages.length); - setOrder( - await normalizeLoadedOrder(newActivityInfo.activityPages), - ); - setVariantsByPage(newActivityInfo.variantsByPage); - setItemWeights(newActivityInfo.itemWeights); - newItemWeights = newActivityInfo.itemWeights; - previousComponentTypeCountsByPage.current = - newActivityInfo.previousComponentTypeCounts || []; - - activityInfo.current = newActivityInfo; - activityInfoString.current = JSON.stringify( - activityInfo.current, - ); - - let workerResult = await createAndInitializePageCoreWorkers( - newActivityInfo.activityPages, - flags, - ); - pageCoreWorkersInfo.current = workerResult.pageCoreWorkersInfo; - errorsActivitySpecific.current.push( - ...normalizeErrors(workerResult.errors, doenetML.current), - ); - } else { - // get initial state and info - - loadedFromInitialState = true; - - // start at page 1 - // if hash doesn't already specify a page, set page to 1 - if (!hash?.match(/^#page(\d+)/)) { - setCurrentPage(1); - } - - let results = await calculateOrderAndVariants({ - activityDefinition, - requestedVariantIndex, - flags, - }); - - errorsActivitySpecific.current.push( - ...normalizeErrors(results.errors, doenetML.current), - ); - - newVariantIndex = results.variantIndex; - setVariantIndex(newVariantIndex); - setNPages(results.order.length); - setOrder(results.order); - setVariantsByPage(results.variantsByPage); - setItemWeights(results.itemWeights); - newItemWeights = results.itemWeights; - previousComponentTypeCountsByPage.current = - results.previousComponentTypeCounts || []; - pageCoreWorkersInfo.current = results.pageCoreWorkersInfo; - - activityInfo.current = results.activityInfo; - activityInfoString.current = JSON.stringify( - activityInfo.current, - ); - } - } - - return { - newItemWeights, - newVariantIndex, - loadedFromInitialState, - }; - } - - async function normalizeLoadedOrder(order: any[]) { - // In case we load an order from the data base that was created before Sept 1, 2023, - // we need to check if the page has a doneetML attribute, - // and load the doenetML if needed - - let newOrder: any[] = []; - - for (let page of order) { - if (page.doenetML === undefined) { - page.doenetML = await retrieveTextFileForCid( - page.cid, - "doenet", - ); - } - newOrder.push(page); - } - - return newOrder; - } - - async function saveLoadedLocalStateToDatabase(localInfo: any) { - if (!flags.allowSaveState || !apiURLs.saveActivityState) { - return {}; - } - - let serverSaveId = await idb_get( - `${activityId}|${attemptNumber}|${cid}|ServerSaveId`, - ); - - let activityStateToBeSavedToDatabase = { - cid, - activityInfo: JSON.stringify(localInfo.activityInfo), - activityState: JSON.stringify(localInfo.activityState), - variantIndex: localInfo.variantIndex, - attemptNumber, - activityId, - saveId: localInfo.saveId, - serverSaveId, - updateDataOnContentChange, - }; - - let resp; - - try { - resp = await axios.post( - apiURLs.saveActivityState, - activityStateToBeSavedToDatabase, - ); - } catch (e) { - // since this is initial load, don't show error message - return { localInfo, cid, attemptNumber }; - } - - if (resp.data.cidChanged === true) { - cidChangedCallback?.(); - } - - let data = resp.data; - - if (!data.success) { - // since this is initial load, don't show error message - return { localInfo, cid, attemptNumber }; - } - - await idb_set( - `${activityId}|${attemptNumber}|${cid}|ServerSaveId`, - data.saveId, - ); - - if (data.stateOverwritten) { - let newLocalInfo = { - activityState: JSON.parse(data.activityState), - activityInfo: JSON.parse(data.activityInfo), - saveId: data.saveId, - variantIndex: data.variantIndex, - }; - - await idb_set( - `${activityId}|${data.attemptNumber}|${data.cid}`, - newLocalInfo, - ); - - return { - changedOnDevice: data.device, - newLocalInfo, - newCid: data.cid, - newAttemptNumber: data.attemptNumber, - }; - } - - return { localInfo, cid, attemptNumber }; - } - - async function saveState({ - overrideThrottle = false, - overrideStage = false, - } = {}) { - if (!flags.allowSaveState && !flags.allowLocalState) { - return; - } - - if ( - (stageRef.current !== "saving" && !overrideStage) || - (!overrideThrottle && - currentPageRef.current === pageAtPreviousSave.current) || - (overrideThrottle && - currentPageRef.current === pageAtPreviousSaveToDatabase.current) - ) { - // haven't gotten a save event from page or no change to be saved - return; - } - - pageAtPreviousSave.current = currentPageRef.current; - - let saveId = nanoid(); - - if (flags.allowLocalState) { - await idb_set( - `${activityId}|${attemptNumberRef.current}|${cidRef.current}`, - { - activityInfo: activityInfo.current, - activityState: { currentPage: currentPageRef.current }, - saveId, - variantIndex: variantIndexRef.current, - }, - ); - } - - if (!flags.allowSaveState) { - return; - } - - activityStateToBeSavedToDatabase.current = { - cid: cidRef.current, - activityInfo: activityInfoString.current, - activityState: JSON.stringify({ - currentPage: currentPageRef.current, - }), - variantIndex: variantIndexRef.current, - attemptNumber: attemptNumberRef.current, - activityId, - saveId, - serverSaveId: serverSaveId.current, - updateDataOnContentChange, - }; - - // mark presence of changes - // so that next call to saveChangesToDatabase will save changes - changesToBeSaved.current = true; - - // if not currently in throttle, save changes to database - await saveChangesToDatabase(overrideThrottle); - } - - async function saveChangesToDatabase(overrideThrottle?: boolean) { - // throttle save to database at 60 seconds - - if ( - !changesToBeSaved.current || - !flags.allowSaveState || - !apiURLs.saveActivityState - ) { - return; - } - - // get the up-to-date value here without a refresh!! - - // just use the ref - - let oldTimeoutId = saveStateToDBTimerId.current; - - if (oldTimeoutId !== null) { - if (overrideThrottle) { - clearTimeout(oldTimeoutId); - } else { - return; - } - } - - changesToBeSaved.current = false; - pageAtPreviousSaveToDatabase.current = currentPageRef.current; - - // check for changes again after 60 seconds - saveStateToDBTimerId.current = setTimeout(() => { - saveStateToDBTimerId.current = null; - saveChangesToDatabase(); - }, 60000); - - // TODO: find out how to test if not online - // and send this sendAlert if not online: - - let pause100 = function () { - return new Promise((resolve, reject) => { - setTimeout(resolve, 100); - }); - }; - - if (savingActivityState.current) { - for (let i = 0; i < 100; i++) { - await pause100(); - - if (!savingActivityState.current) { - break; - } - } - } - - activityStateToBeSavedToDatabase.current.serverSaveId = - serverSaveId.current; - - let resp; - - try { - resp = await axios.post( - apiURLs.saveActivityState, - activityStateToBeSavedToDatabase.current, - ); - } catch (e) { - sendAlert( - "Error synchronizing data. Changes not saved to the server.", - "error", - ); - - savingActivityState.current = false; - return; - } - - savingActivityState.current = false; - - if (resp.status === null) { - sendAlert( - "Error synchronizing data. Changes not saved to the server. Are you connected to the internet?", - "error", - ); - return; - } - - let data = resp.data; - - if (!data.success) { - sendAlert(data.message, "error"); - return; - } - - serverSaveId.current = data.saveId; - - if (flags.allowLocalState) { - await idb_set( - `${activityId}|${attemptNumberRef.current}|${cidRef.current}|ServerSaveId`, - data.saveId, - ); - } - - if (data.stateOverwritten) { - // if a new attempt number was generated, - // then we reset the activity to the new state - if (attemptNumberRef.current !== Number(data.attemptNumber)) { - resetActivity({ - changedOnDevice: data.device, - newCid: data.cid, - newAttemptNumber: Number(data.attemptNumber), - }); - } else if (cidRef.current !== data.cid) { - // if the cid changed without the attemptNumber changing, something went wrong - setIsInErrorState?.(true); - setErrMsg("Content changed unexpectedly!"); - return; - } - - // if only the activity state changed, - // just ignore it as it is only changing the page and we can leave it at the old page - } - - // TODO: send message so that UI can show changes have been synchronized - } - - async function initializeUserAssignmentTables(newItemWeights: any[]) { - //Initialize user_assignment tables - if (flags.allowSaveSubmissions && apiURLs.initAssignmentAttempt) { - try { - let resp = await axios.post(apiURLs.initAssignmentAttempt, { - activityId, - weights: newItemWeights, - attemptNumber, - }); - - if (resp.status === null) { - sendAlert( - `Could not initialize assignment tables. Are you connected to the internet?`, - "error", - ); - } else if (!resp.data.success) { - sendAlert( - `Could not initialize assignment tables: ${resp.data.message}.`, - "error", - ); - } - } catch (e: any) { - sendAlert( - `Could not initialize assignment tables: ${e.message}.`, - "error", - ); - } - } - } - - async function receivedSaveFromPage() { - // activity state isn't saved until a first save from a page - if (stage !== "saving" && !settingUp.current) { - setStage("saving"); - } - - checkIfCidChanged?.(cid); - - if (viewerWasUnmounted.current) { - await saveState({ overrideThrottle: true, overrideStage: true }); - } - } - - function clickNext() { - setCurrentPage((was) => Math.min(nPages, was + 1)); - - let event = { - verb: "interacted", - object: { objectType: "button", objectname: "next page button" }, - result: { newPage: Math.min(nPages, currentPage + 1) }, - context: { oldPage: currentPage }, - }; - - recordEvent(event); - } - - function clickPrevious() { - setCurrentPage((was) => Math.max(1, was - 1)); - - let event = { - verb: "interacted", - object: { - objectType: "button", - objectname: "previous page button", - }, - result: { newPage: Math.max(1, currentPage - 1) }, - context: { oldPage: currentPage }, - }; - - recordEvent(event); - } - - function recordEvent(event: any) { - if (!flags.allowSaveEvents || !apiURLs.recordEvent) { - return; - } - - const payload = { - activityId, - cidForActivity: cid, - attemptNumber, - activityVariantIndex: variantIndex, - timestamp: new Date().toISOString().slice(0, 19).replace("T", " "), - version: "0.1.1", - verb: event.verb, - object: JSON.stringify(event.object), - result: JSON.stringify(event.result), - context: JSON.stringify(event.context), - }; - - axios - .post(apiURLs.recordEvent, payload) - .then((resp) => { - // console.log(">>>>Activity Viewer resp",resp.data) - }) - .catch((e) => { - console.error(`Error saving event: ${e.message}`); - }); - } - - function onChangeVisibility(isVisible: boolean, pageInd: number) { - if (!paginate) { - setPageInfo((was) => { - let newObj = { ...was }; - let newVisible = [...newObj.pageIsVisible]; - newVisible[pageInd] = isVisible; - newObj.pageIsVisible = newVisible; - - if (!isVisible && newObj.pageIsActive[pageInd]) { - let newActive = [...newObj.pageIsActive]; - newActive[pageInd] = false; - newObj.pageIsActive = newActive; - - if (newObj.waitingForPagesCore === pageInd) { - newObj.waitingForPagesCore = null; - } - } - - return newObj; - }); - } - } - - function coreCreatedCallback(pageInd: number) { - setPageInfo((was) => { - let newObj = { ...was }; - if (newObj.waitingForPagesCore === pageInd) { - newObj.waitingForPagesCore = null; - } - - let newPageCoreCreated = [...newObj.pageCoreCreated]; - newPageCoreCreated[pageInd] = true; - newObj.pageCoreCreated = newPageCoreCreated; - - return newObj; - }); - } - - function pageRenderedCallback(pageInd: number) { - let newRenderedPages: boolean[] = []; - setRenderedPages((was) => { - newRenderedPages = [...was]; - newRenderedPages[pageInd] = true; - return newRenderedPages; - }); - - if ( - newRenderedPages?.length === nPages && - newRenderedPages.every((x) => x) - ) { - allPagesRendered.current = true; - } - } - - async function submitAllAndFinishAssessment() { - setProcessingSubmitAll(true); - - let submitAndSavePromises: Promise[] = []; - - for (let [ - pageInd, - coreWorkerInfo, - ] of pageCoreWorkersInfo.current.entries()) { - if (pageInfo.pageCoreCreated[pageInd]) { - let actionId = nanoid(); - let resolveSubmitAndSavePromise: Function; - let rejectSubmitAndSavePromise: Function; - let coreWorker = coreWorkerInfo.coreWorker; - - submitAndSavePromises.push( - new Promise((resolve, reject) => { - resolveSubmitAndSavePromise = resolve; - rejectSubmitAndSavePromise = reject; - }), - ); - - let submitAllAndSaveListener = function (e: any) { - if ( - e.data.messageType === "resolveAction" && - e.data.args.actionId === actionId - ) { - coreWorker.postMessage({ - messageType: "saveImmediately", - }); - } else if (e.data.messageType === "saveImmediatelyResult") { - coreWorker.removeEventListener( - "message", - submitAllAndSaveListener, - ); - - if (e.data.success) { - resolveSubmitAndSavePromise(); - } else { - rejectSubmitAndSavePromise(); - } - } - }; - - coreWorker.addEventListener( - "message", - submitAllAndSaveListener, - ); - - coreWorker.postMessage({ - messageType: "submitAllAnswers", - args: { actionId }, - }); - } - } - - try { - await Promise.all(submitAndSavePromises); - - await terminateAllCores(); - - await saveState({ overrideThrottle: true }); - } catch (e) { - sendAlert( - `An error occurred. Assessment was not successfully submitted.`, - "error", - ); - - setFinishAssessmentMessageOpen(false); - setProcessingSubmitAll(false); - - // return so don't set activity as completed - return; - } - - setActivityAsCompleted?.(); - - setPageInfo((was) => { - let newObj = { ...was }; - newObj.waitingForPagesCore = null; - newObj.pageCoreCreated = []; - return newObj; - }); - } - - async function terminateAllCores() { - let terminatePromises: Promise[] = []; - - for (let [ - pageInd, - coreWorkerInfo, - ] of pageCoreWorkersInfo.current.entries()) { - if (pageInfo.pageCoreCreated[pageInd]) { - let resolveTerminatePromise: Function; - let rejectTerminatePromise: Function; - let coreWorker = coreWorkerInfo.coreWorker; - - terminatePromises.push( - new Promise((resolve, reject) => { - resolveTerminatePromise = resolve; - rejectTerminatePromise = reject; - }), - ); - - let terminateListener = function (e: any) { - if (e.data.messageType === "terminated") { - coreWorker.removeEventListener( - "message", - terminateListener, - ); - - resolveTerminatePromise(); - } else if (e.data.messageType === "terminateFailed") { - coreWorker.removeEventListener( - "message", - terminateListener, - ); - - rejectTerminatePromise(); - } - }; - - coreWorker.addEventListener("message", terminateListener); - - coreWorker.postMessage({ - messageType: "terminate", - }); - } - } - - await Promise.all(terminatePromises); - } - - function setPageErrorsAndWarningsCallback( - errorsAndWarnings: { - errors: ErrorDescription[]; - warnings: WarningDescription[]; - }, - pageInd: number, - ) { - errorsAndWarningsByPage.current[pageInd] = errorsAndWarnings; - - setErrorsAndWarningsCallback?.(collateErrorsAndWarnings()); - } - - function collateErrorsAndWarnings() { - let allErrors = [...errorsActivitySpecific.current]; - - let allWarnings: WarningDescription[] = []; - - for (let errWarn of errorsAndWarningsByPage.current) { - if (errWarn) { - allErrors.push(...errWarn.errors); - allWarnings.push(...errWarn.warnings); - } - } - - return { - errors: allErrors, - warnings: allWarnings, - }; - } - - if (errMsg !== "") { - let errorIcon = ( - - - - ); - return ( -
- {errorIcon} {errMsg} -
- ); - } - - if ( - lastDoenetMLFromProps !== doenetMLFromProps || - lastCidFromProps !== cidFromProps || - attemptNumber !== attemptNumberFromProps || - requestedVariantIndex !== requestedVariantIndexFromProps - ) { - settingUp.current = true; - - setInfoFromProps({ - lastDoenetMLFromProps: doenetMLFromProps, - lastCidFromProps: cidFromProps, - attemptNumber: attemptNumberFromProps, - requestedVariantIndex: requestedVariantIndexFromProps, - }); - - errorsAndWarningsByPage.current = []; - errorsActivitySpecific.current = []; - - // if in a timeout to save changes from a previous instance, - // cancel that timeout - let oldTimeoutId = saveStateToDBTimerId.current; - if (oldTimeoutId !== null) { - clearTimeout(oldTimeoutId); - } - - setStage("recalcParams"); - setActivityContentChanged(true); - return null; - } - - if (stage === "wait") { - return null; - } - - if (stage === "recalcParams") { - setStage("wait"); - calculateCidDefinition(); - return null; - } - - // at this point, we have - // attemptNumber, requestedVariantIndex, cid, activityDefinition - - if (activityDefinition?.type?.toLowerCase() !== "activity") { - setIsInErrorState?.(true); - setErrMsg("Invalid activity definition: type is not activity"); - return null; - } - - if (activityContentChanged) { - setActivityContentChanged(false); - setActivityAttemptNumberSetUp(0); - - previousComponentTypeCountsByPage.current = []; - - setStage("wait"); - - loadState().then(async (results) => { - if (results) { - if (results.loadedFromInitialState) { - await initializeUserAssignmentTables( - results.newItemWeights, - ); - } - setStage("continue"); - setActivityAttemptNumberSetUp(attemptNumber); - - let allPossibleVariants; - if ( - activityDefinition.numVariants === undefined && - activityDefinition.children.length === 1 && - activityDefinition.children[0].type === "page" - ) { - // if have a single page, then use the names of the variants - // defined for that page (rather than the default of numbering them) - - // TODO: should we save these so we don't have to recalculate them? - // Right now, if didn't load state, then we calculated this twice - // as call returnAllPossibleVariants in loadState - allPossibleVariants = - await returnAllPossibleVariantsFromCoreWorker( - pageCoreWorkersInfo.current[0].coreWorker, - ); - } - - if (!allPossibleVariants) { - allPossibleVariants = [ - ...Array(activityInfo.current.numVariants).keys(), - ].map((i) => String(i + 1)); - } - - generatedVariantCallback?.({ - index: Number(results.newVariantIndex), // TODO: is Number is needed? - numVariants: activityInfo.current.numVariants, - allPossibleVariants, - }); - } - settingUp.current = false; - }); - - return null; - } - - if (pageInfo.waitingForPagesCore === null) { - // check current page first - if (currentPage) { - for (let pageInd of [currentPage - 1, ...Array(nPages).keys()]) { - let isVisible = pageInfo.pageIsVisible[pageInd]; - if ( - (isVisible || currentPage === pageInd + 1) && - !pageInfo.pageIsActive[pageInd] - ) { - // activate either the current page or an inactive page that is visible - - // if we need to create core - // then stop here to not create multiple cores at once - let waitingAgain = !pageInfo.pageCoreCreated[pageInd]; - - setPageInfo((was) => { - let newObj = { ...was }; - let newActive = [...newObj.pageIsActive]; - newActive[pageInd] = true; - newObj.pageIsActive = newActive; - if (!newObj.pageCoreCreated[pageInd]) { - newObj.waitingForPagesCore = pageInd; - } - return newObj; - }); - - if (waitingAgain) { - break; - } - } - } - } - } - - saveState(); - - let title =

{activityDefinition.title}

; - - let pages: React.JSX.Element[] = []; - - if (order && variantsByPage) { - for (let [ind, page] of order.entries()) { - let thisPageIsActive = false; - if (paginate) { - if (ind === currentPage - 1) { - // the current page is always active - thisPageIsActive = true; - } else if ( - pageInfo.pageCoreCreated[currentPage - 1] && - ind === currentPage - ) { - // if the current page already has core created, activate next page - thisPageIsActive = true; - } else if ( - pageInfo.pageCoreCreated[currentPage - 1] && - (currentPage === nPages || - pageInfo.pageCoreCreated[currentPage]) && - ind === currentPage - 2 - ) { - // if current page and page after current page (if exists) already have current page - // activate previous page - thisPageIsActive = true; - } - } else { - // pageIsActive is used only if not paginated - thisPageIsActive = pageInfo.pageIsActive[ind]; - } - - let prefixForIds = - activityPrefixUnescaped + (nPages > 1 ? `page${ind + 1}` : ""); - - let pageViewer = ( - // @ts-ignore - - setPageErrorsAndWarningsCallback(x, ind) - } - updateCreditAchievedCallback={updateCreditAchievedCallback} - setIsInErrorState={setIsInErrorState} - updateAttemptNumber={updateAttemptNumber} - saveStateCallback={receivedSaveFromPage} - updateDataOnContentChange={updateDataOnContentChange} - coreCreatedCallback={() => coreCreatedCallback(ind)} - renderersInitializedCallback={() => - pageRenderedCallback(ind) - } - hideWhenNotCurrent={paginate} - prefixForIds={prefixForIds} - apiURLs={apiURLs} - location={location} - navigate={navigate} - linkSettings={linkSettings} - errorsActivitySpecific={errorsActivitySpecific.current} - scrollableContainer={scrollableContainer} - darkMode={darkMode} - showAnswerTitles={showAnswerTitles} - /> - ); - - if (!paginate) { - pageViewer = ( - - onChangeVisibility(isVisible, ind) - } - > -
{pageViewer}
-
- ); - } - - pages.push( -
- {pageViewer} -
, - ); - } - } - - let pageControlsTop: React.JSX.Element | null = null; - let pageControlsBottom: React.JSX.Element | null = null; - if (paginate && nPages > 1) { - pageControlsTop = ( -
- -

- {} Page {currentPage} of {nPages} {} -

- -
- ); - - if (renderedPages[currentPage - 1]) { - pageControlsBottom = ( -
- -

- {} Page {currentPage} of {nPages} {} -

- -
- ); - } - } - - let finishAssessmentPrompt: React.JSX.Element | null = null; - - if (showFinishButton) { - if (finishAssessmentMessageOpen) { - finishAssessmentPrompt = ( -
-
- Are you sure you want to finish this assessment? -
-
- - - - -
-
- ); - } else { - finishAssessmentPrompt = ( -
-
-
- - setFinishAssessmentMessageOpen(true) - } - dataTest="FinishAssessmentPrompt" - value="Finish assessment" - > -
-
-
- ); - } - } - - let paddingStyle: { paddingBottom?: string } = {}; - if (addBottomPadding) { - paddingStyle.paddingBottom = "50vh"; - } - - let activityErrors: React.JSX.Element[] | null = null; - if (errorsActivitySpecific.current.length > 0) { - const errorsToDisplay = errorsActivitySpecific.current.filter( - (x) => x.displayInActivity, - ); - let errorStyle = { - backgroundColor: "#ff9999", - textAlign: "center" as const, - borderWidth: 3, - borderStyle: "solid", - }; - activityErrors = errorsToDisplay.map((err, i) => { - let rangeMessage: React.JSX.Element | null = null; - if (err.doenetMLrange?.lineBegin !== undefined) { - rangeMessage = ( - <> -
- - {"Found on " + - printDoenetMLrange(err.doenetMLrange) + - "."} - - - ); - } - - return ( -
- Error: {err.message} - {rangeMessage} -
- ); - }); - } - - return ( -
- {activityErrors} - {pageControlsTop} - {title} - {pages} - {pageControlsBottom} - {finishAssessmentPrompt} -
- ); -} diff --git a/packages/doenetml/src/Viewer/PageViewer.jsx b/packages/doenetml/src/Viewer/PageViewer.jsx index 1b748c942..56f123e7f 100644 --- a/packages/doenetml/src/Viewer/PageViewer.jsx +++ b/packages/doenetml/src/Viewer/PageViewer.jsx @@ -11,14 +11,14 @@ import { serializedComponentsReviver, cesc, data_format_version, + cidFromText, } from "@doenet/utils"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons"; import { rendererState } from "./useDoenetRenderer"; import { atom, atomFamily, useRecoilCallback, useRecoilValue } from "recoil"; -import { get as idb_get, set as idb_set } from "idb-keyval"; -import axios from "axios"; -import { createCoreWorker, initializeCoreWorker } from "../utils/activityUtils"; +import { get as idb_get } from "idb-keyval"; +import { createCoreWorker, initializeCoreWorker } from "../utils/pageUtils"; const rendererUpdatesToIgnore = atomFamily({ key: "rendererUpdatesToIgnore", @@ -32,39 +32,29 @@ export const PageContext = createContext(); export function PageViewer({ userId, activityId, - cidForActivity, - cid, doenetML, - coreWorkerInfo, pageNumber = "1", - previousComponentTypeCounts, - pageIsActive, - pageIsCurrent, - itemNumber, + render: pageIsActive = true, + isCurrent: pageIsCurrent = true, + hideWhenNotCurrent = false, + itemNumber = 1, attemptNumber = 1, - forceDisable, - forceShowCorrectness, - forceShowSolution, - forceUnsuppressCheckwork, - generatedVariantCallback, // currently not passed in + forceDisable = false, + forceShowCorrectness = false, + forceShowSolution = false, + forceUnsuppressCheckwork = false, + generatedVariantCallback, flags, - activityVariantIndex, requestedVariantIndex, setErrorsAndWarningsCallback, updateCreditAchievedCallback, setIsInErrorState, updateAttemptNumber, - saveStateCallback, updateDataOnContentChange, - coreCreatedCallback, - renderersInitializedCallback, - hideWhenNotCurrent, prefixForIds = "", - apiURLs = {}, location = {}, navigate, linkSettings = { viewURL: "/portfolioviewer", editURL: "/publiceditor" }, - errorsActivitySpecific = {}, scrollableContainer, darkMode, showAnswerTitles, @@ -158,7 +148,7 @@ export function PageViewer({ const [errMsg, setErrMsg] = useState(null); - const lastCid = useRef(null); + const cid = useRef(null); const lastDoenetML = useRef(null); const lastPageNumber = useRef(null); const lastAttemptNumber = useRef(null); @@ -196,6 +186,8 @@ export function PageViewer({ const [ignoreRendererError, setIgnoreRendererError] = useState(false); + const [coreWorkerInfo, setCoreWorkerInfo] = useState(null); + let hash = location.hash; const contextForRenderers = { @@ -215,6 +207,31 @@ export function PageViewer({ .replaceAll("-", "_") || "1"; useEffect(() => { + async function initialize() { + let coreWorker = createCoreWorker(); + + let theInfo = { + coreWorker, + doenetML, + flags, + }; + + setCoreWorkerInfo(theInfo); + + try { + await initializeCoreWorker(theInfo); + } catch (e) { + setErrMsg(`Error initializing activity: ${e.message}`); + } + } + + initialize(); + }, []); + + useEffect(() => { + if (!coreWorkerInfo) { + return; + } coreWorkerInfo.coreWorker.onmessage = function (e) { // console.log("message from core", e.data); if (e.data.messageType === "updateRenderers") { @@ -255,7 +272,7 @@ export function PageViewer({ }); } setStage("coreCreated"); - coreCreatedCallback?.(); + // coreCreatedCallback?.(); } else if (e.data.messageType === "initializeRenderers") { if ( coreInfo.current && @@ -276,7 +293,7 @@ export function PageViewer({ } else if (e.data.messageType === "updateCreditAchieved") { updateCreditAchievedCallback?.(e.data.args); } else if (e.data.messageType === "savedState") { - saveStateCallback?.(); + // saveStateCallback?.(); } else if (e.data.messageType === "sendAlert") { console.log(`Sending alert message: ${e.data.args.message}`); sendAlert(e.data.args.message, e.data.args.alertType); @@ -287,10 +304,6 @@ export function PageViewer({ resolveAllStateVariables.current(e.data.args); } else if (e.data.messageType === "returnErrorWarnings") { let errorWarnings = e.data.args; - errorWarnings.errors = [ - ...errorsActivitySpecific, - ...errorWarnings.errors, - ]; console.log(errorWarnings); resolveErrorWarnings.current(errorWarnings); } else if (e.data.messageType === "componentRangePieces") { @@ -327,15 +340,20 @@ export function PageViewer({ ...e.data, subject: "SPLICE.sendEvent", }); + } else if (e.data.messageType === "allPossibleVariants") { + window.postMessage({ + ...e.data, + subject: "SPLICE.allPossibleVariants", + }); } else if (e.data.messageType === "terminated") { - reinitializeCoreAndTerminateAnimations(); + reinitializeCoreAndTerminateAnimations(coreWorkerInfo); } }; - }, [coreWorkerInfo.coreWorker, location]); + }, [coreWorkerInfo?.coreWorker, location]); useEffect(() => { return () => { - coreWorkerInfo.coreWorker.postMessage({ + coreWorkerInfo?.coreWorker.postMessage({ messageType: "terminate", }); }; @@ -363,6 +381,9 @@ export function PageViewer({ }); useEffect(() => { + if (!coreWorkerInfo) { + return; + } if (pageNumber !== null) { window["returnAllStateVariables" + postfixForWindowFunctions] = function () { @@ -397,7 +418,7 @@ export function PageViewer({ }); }; } - }, [pageNumber]); + }, [pageNumber, coreWorkerInfo]); useEffect(() => { return () => { @@ -410,6 +431,9 @@ export function PageViewer({ }, []); useEffect(() => { + if (!coreWorkerInfo) { + return; + } document.addEventListener("visibilitychange", () => { coreWorkerInfo.coreWorker.postMessage({ messageType: "visibilityChange", @@ -418,10 +442,10 @@ export function PageViewer({ }, }); }); - }, []); + }, [coreWorkerInfo]); useEffect(() => { - if (hash && coreCreated.current && coreWorkerInfo.coreWorker) { + if (hash && coreCreated.current && coreWorkerInfo?.coreWorker) { let anchor = hash.slice(1); if (anchor.substring(0, prefixForIds.length) === prefixForIds) { coreWorkerInfo.coreWorker.postMessage({ @@ -435,7 +459,13 @@ export function PageViewer({ }); } } - }, [location, hash, coreCreated.current, coreWorkerInfo.coreWorker]); + }, [ + location, + hash, + coreCreated.current, + coreWorkerInfo, + coreWorkerInfo?.coreWorker, + ]); useEffect(() => { if (hash && documentRenderer && pageIsActive) { @@ -510,7 +540,7 @@ export function PageViewer({ [location], ); - async function reinitializeCoreAndTerminateAnimations() { + async function reinitializeCoreAndTerminateAnimations(newCoreWorkerInfo) { preventMoreAnimations.current = true; coreWorkerInfo.coreWorker.terminate(); coreWorkerInfo.coreWorker = createCoreWorker(); @@ -523,7 +553,7 @@ export function PageViewer({ animationInfo.current = {}; actionsBeforeCoreCreated.current = []; - await initializeCoreWorker(coreWorkerInfo); + await initializeCoreWorker(newCoreWorkerInfo); } async function callAction({ @@ -639,7 +669,7 @@ export function PageViewer({ if (coreCreated.current) { // Note: it is possible that core has been terminated, so we need the question mark - coreWorkerInfo.coreWorker.postMessage({ + coreWorkerInfo.coreWorker?.postMessage({ messageType: "requestAction", args: actionArgs, }); @@ -874,12 +904,14 @@ export function PageViewer({ const coreIdWhenCalled = coreId.current; let loadedState = false; + cid.current = await cidFromText(doenetML); + if (flags.allowLocalState) { let localInfo; try { localInfo = await idb_get( - `${activityId}|${pageNumber}|${attemptNumber}|${cid}`, + `${activityId}|${pageNumber}|${attemptNumber}|${cid.current}`, ); if (localInfo.data_format_version !== data_format_version) { // the data saved does not match the current version, so we ignore it @@ -890,41 +922,6 @@ export function PageViewer({ } if (localInfo) { - if (flags.allowSaveState) { - // attempt to save local info to database, - // resetting data to that from database if it has changed since last save - - let result = - await saveLoadedLocalStateToDatabase(localInfo); - - if (result.changedOnDevice) { - if (Number(result.newAttemptNumber) !== attemptNumber) { - resetPage({ - changedOnDevice: result.changedOnDevice, - newCid: result.newCid, - newAttemptNumber: Number( - result.newAttemptNumber, - ), - }); - return; - } else if (result.newCid !== cid) { - // if cid changes for the same attempt number, then something went wrong - setIsInErrorState?.(true); - setErrMsg(`content changed unexpectedly!`); - } - - // if just the localInfo changed, use that instead - localInfo = result.newLocalInfo; - console.log( - `sending alert: Reverted page to state saved on device ${result.changedOnDevice}`, - ); - sendAlert( - `Reverted page to state saved on device ${result.changedOnDevice}`, - "info", - ); - } - } - const coreState = JSON.parse( localInfo.coreState, serializedComponentsReviver, @@ -967,11 +964,11 @@ export function PageViewer({ } } - if (!loadedState && apiURLs.postMessages) { + if (!loadedState) { if (flags.allowLoadState) { try { let resp = await getStateViaSplice({ - cid, + cid: cid.current, pageNumber, attemptNumber, activityId, @@ -986,55 +983,6 @@ export function PageViewer({ return; } } - } else if (!loadedState && apiURLs.loadPageState) { - // if didn't load state from local storage, try to load from database - - // even if allowLoadState is false, - // still call loadPageState, in which case it will only retrieve the initial page state - - const payload = { - params: { - cid, - pageNumber, - attemptNumber, - activityId, - userId, - requestedVariantIndex, - allowLoadState: flags.allowLoadState, - showCorrectness: flags.showCorrectness, - solutionDisplayMode: flags.solutionDisplayMode, - showFeedback: flags.showFeedback, - showHints: flags.showHints, - autoSubmit: flags.autoSubmit, - }, - }; - - try { - let resp = await axios.get(apiURLs.loadPageState, payload); - if (!resp.data.success) { - if (flags.allowLoadState) { - setIsInErrorState?.(true); - setErrMsg( - `Error loading page state: ${resp.data.message}`, - ); - return; - } else { - // ignore this error if didn't allow loading of page state - } - } - - if (resp.data.loadedState) { - processLoadedPageState(resp); - } - } catch (e) { - if (flags.allowLoadState) { - setIsInErrorState?.(true); - setErrMsg(`Error loading page state: ${e.message}`); - return; - } else { - // ignore this error if didn't allow loading of page state - } - } } //Guard against the possibility that parameters changed while waiting @@ -1122,82 +1070,20 @@ export function PageViewer({ }; } - async function saveLoadedLocalStateToDatabase(localInfo) { - // TODO: handle postMessages case - if (!flags.allowSaveState || !apiURLs.savePageState) { - return {}; - } - - let serverSaveId = await idb_get( - `${activityId}|${pageNumber}|${attemptNumber}|${cid}|ServerSaveId`, - ); - - let pageStateToBeSavedToDatabase = { - cid, - coreInfo: localInfo.coreInfo, - coreState: localInfo.coreState, - rendererState: localInfo.rendererState, - pageNumber, - attemptNumber, - activityId, - saveId: localInfo.saveId, - serverSaveId, - updateDataOnContentChange, + async function startCore() { + let theInfo = { + coreWorker: coreWorkerInfo.coreWorker, + doenetML, + flags, }; + setCoreWorkerInfo(theInfo); - let resp; - - try { - resp = await axios.post( - apiURLs.savePageState, - pageStateToBeSavedToDatabase, - ); - } catch (e) { - // since this is initial load, don't show error message - return { localInfo, cid, attemptNumber }; - } - - let data = resp.data; - - if (!data.success) { - // since this is initial load, don't show error message - return { localInfo, cid, attemptNumber }; - } - - await idb_set( - `${activityId}|${pageNumber}|${attemptNumber}|${cid}|ServerSaveId`, - data.saveId, - ); - - if (data.stateOverwritten) { - let newLocalInfo = { - data_format_version, - coreState: data.coreState, - rendererState: data.rendererState, - coreInfo: data.coreInfo, - saveId: data.saveId, - }; - - await idb_set( - `${activityId}|${pageNumber}|${data.attemptNumber}|${data.cid}`, - newLocalInfo, - ); - - return { - changedOnDevice: data.device, - newLocalInfo, - newCid: data.cid, - newAttemptNumber: data.attemptNumber, - }; - } - - return { localInfo, cid, attemptNumber }; - } - - async function startCore() { //Kill the current core if it exists if (coreCreated.current) { - await reinitializeCoreAndTerminateAnimations(); + await reinitializeCoreAndTerminateAnimations(theInfo); + } else { + // otherwise, just initialize to give it the current DoenetML + await initializeCoreWorker(theInfo); } resolveActionPromises.current = {}; @@ -1208,10 +1094,8 @@ export function PageViewer({ args: { coreId: coreId.current, userId, - cid, + cid: cid.current, activityId, - previousComponentTypeCounts, - cidForActivity, theme: darkMode, requestedVariantIndex, pageNumber, @@ -1219,7 +1103,6 @@ export function PageViewer({ itemNumber, updateDataOnContentChange, serverSaveId: initialCoreData.current.serverSaveId, - activityVariantIndex, requestedVariant: initialCoreData.current.requestedVariant, stateVariableChanges: initialCoreData.current.coreState ? JSON.stringify( @@ -1227,7 +1110,6 @@ export function PageViewer({ serializedComponentsReplacer, ) : undefined, - apiURLs: apiURLs, }, }); @@ -1299,7 +1181,11 @@ export function PageViewer({ } } - // first, if lastCid or lastDoenetML don't match props + if (!coreWorkerInfo) { + return null; + } + + // first, if last parameters don't match props // set state to props and record that that need a new core let changedState = false; @@ -1307,10 +1193,6 @@ export function PageViewer({ lastDoenetML.current = doenetML; changedState = true; } - if (lastCid.current !== cid) { - lastCid.current = cid; - changedState = true; - } if (lastPageNumber.current !== pageNumber) { lastPageNumber.current = pageNumber; @@ -1382,12 +1264,12 @@ export function PageViewer({ ) { // we've moved off this page, but core is still being created // so reinitialize core - reinitializeCoreAndTerminateAnimations(); + reinitializeCoreAndTerminateAnimations(coreWorkerInfo); setStage("readyToCreateCore"); } - if (hideWhenNotCurrent && !pageIsCurrent) { + if ((hideWhenNotCurrent && !pageIsCurrent) || !pageIsActive) { return null; } diff --git a/packages/doenetml/src/Viewer/renderers/codeEditor-ts.tsx b/packages/doenetml/src/Viewer/renderers/codeEditor-ts.tsx index e2786209f..25718cc93 100644 --- a/packages/doenetml/src/Viewer/renderers/codeEditor-ts.tsx +++ b/packages/doenetml/src/Viewer/renderers/codeEditor-ts.tsx @@ -96,6 +96,7 @@ export default React.memo(function CodeEditor(props) { { diff --git a/packages/doenetml/src/Viewer/renderers/image.jsx b/packages/doenetml/src/Viewer/renderers/image.jsx index 76b798ed6..59a2d3d7a 100644 --- a/packages/doenetml/src/Viewer/renderers/image.jsx +++ b/packages/doenetml/src/Viewer/renderers/image.jsx @@ -1,6 +1,5 @@ import React, { useEffect, useState, useContext, useRef } from "react"; import { BoardContext, IMAGE_LAYER_OFFSET } from "./graph"; -import { retrieveMediaForCid } from "@doenet/utils"; import useDoenetRenderer from "../useDoenetRenderer"; import { sizeToCSS } from "./utils/css"; import VisibilitySensor from "react-visibility-sensor-v2"; @@ -64,15 +63,7 @@ export default React.memo(function Image(props) { useEffect(() => { if (SVs.cid) { - retrieveMediaForCid(SVs.cid, SVs.mimeType) - .then((result) => { - // console.log('retrieved media') - // console.log(result) - setUrl(result.mediaURL); - }) - .catch((e) => { - //Ignore errors for now - }); + // TODO: need new approach for getting media } }, []); diff --git a/packages/doenetml/src/doenetml.tsx b/packages/doenetml/src/doenetml.tsx index baca8caec..5cf045c8a 100644 --- a/packages/doenetml/src/doenetml.tsx +++ b/packages/doenetml/src/doenetml.tsx @@ -2,7 +2,7 @@ import "./DoenetML.css"; // @ts-ignore import { prng_alea } from "esm-seedrandom"; import React, { useCallback, useRef, useState } from "react"; -import { ActivityViewer } from "./Viewer/ActivityViewer"; +import { PageViewer } from "./Viewer/PageViewer"; import { RecoilRoot } from "recoil"; import { MathJaxContext } from "better-react-mathjax"; import { mathjaxConfig } from "@doenet/utils"; @@ -95,22 +95,18 @@ const theme = extendTheme({ export function DoenetViewer({ doenetML, flags: specifiedFlags = {}, - cid, activityId, + prefixForIds = "", userId, attemptNumber = 1, + itemNumber = 1, + render = true, + isCurrent = true, + hideWhenNotCurrent = false, requestedVariantIndex, updateCreditAchievedCallback, - updateActivityStatusCallback, updateAttemptNumber, - pageChangedCallback, - paginate = false, - showFinishButton, - cidChangedCallback, - checkIfCidChanged, - setActivityAsCompleted, setIsInErrorState, - apiURLs, generatedVariantCallback: specifiedGeneratedVariantCallback, setErrorsAndWarningsCallback, forceDisable = false, @@ -119,11 +115,9 @@ export function DoenetViewer({ forceUnsuppressCheckwork = false, addVirtualKeyboard = true, externalVirtualKeyboardProvided = false, - addBottomPadding = false, location, navigate, updateDataOnContentChange = false, - idsIncludeActivityId = true, linkSettings, scrollableContainer, darkMode = "light", @@ -132,22 +126,18 @@ export function DoenetViewer({ }: { doenetML: string; flags?: DoenetMLFlagsSubset; - cid?: string; activityId?: string; + prefixForIds?: string; userId?: string; attemptNumber?: number; + itemNumber?: number; + render?: boolean; + isCurrent?: boolean; + hideWhenNotCurrent?: boolean; requestedVariantIndex?: number; updateCreditAchievedCallback?: Function; - updateActivityStatusCallback?: Function; updateAttemptNumber?: Function; - pageChangedCallback?: Function; - paginate?: boolean; - showFinishButton?: boolean; - cidChangedCallback?: Function; - checkIfCidChanged?: Function; - setActivityAsCompleted?: Function; setIsInErrorState?: Function; - apiURLs?: any; generatedVariantCallback?: Function; setErrorsAndWarningsCallback?: Function; forceDisable?: boolean; @@ -156,11 +146,9 @@ export function DoenetViewer({ forceUnsuppressCheckwork?: boolean; addVirtualKeyboard?: boolean; externalVirtualKeyboardProvided?: boolean; - addBottomPadding?: boolean; location?: any; navigate?: any; updateDataOnContentChange?: boolean; - idsIncludeActivityId?: boolean; linkSettings?: { viewURL: string; editURL: string }; scrollableContainer?: HTMLDivElement | Window; darkMode?: "dark" | "light"; @@ -173,13 +161,7 @@ export function DoenetViewer({ allPossibleVariants: ["a"], }); - const thisPropSet = [ - doenetML, - cid, - activityId, - userId, - requestedVariantIndex, - ]; + const thisPropSet = [doenetML, activityId, userId, requestedVariantIndex]; const lastPropSet = useRef([]); const variantIndex = useRef(1); @@ -258,26 +240,23 @@ export function DoenetViewer({ ) : null; const viewer = ( - s) - .map(Number); - - delete documentProps.itemweights; - } - - jsonDefinition.shuffleItemWeights = - documentProps.shuffleitemweights !== undefined && - (documentProps.shuffleitemweights === true || - documentProps.shuffleitemweights.toLowerCase() === "true"); - - delete documentProps.shuffleitemweights; - - jsonDefinition.isSinglePage = - documentProps.issinglepage !== undefined && - (documentProps.issinglepage === true || - documentProps.issinglepage.toLowerCase() === "true"); - - delete documentProps.issinglepage; - - if (documentProps.xmlns) { - if ( - documentProps.xmlns.slice(0, 34) === - "https://doenet.org/spec/doenetml/v" - ) { - jsonDefinition.version = documentProps.xmlns.slice(34); - xmlns = documentProps.xmlns; - delete documentProps.xmlns; - } else { - errors.push({ - message: `Invalid activity definition: unrecognized xmlns`, - doenetMLrange: convertDoenetMLAttrRange( - serializedDocument.attributeRanges.xmlns, - ), - displayInActivity: true, - }); - - return { - success: false, - errors, - }; - } - } else { - console.warn("no xmlns of activity!"); - } - - if (documentProps.numvariants) { - jsonDefinition.numVariants = Number(documentProps.numvariants); - delete documentProps.numvariants; - } - - if (Object.keys(documentProps).length > 0) { - let begin = Infinity; - let end = -Infinity; - for (let prop in documentProps) { - let attrRange = convertDoenetMLAttrRange( - serializedDocument.attributeRanges[prop], - ); - begin = Math.min(begin, attrRange.begin); - end = Math.max(end, attrRange.end); - } - - errors.push({ - message: `Invalid activity definition: invalid document attributes: ${Object.keys( - documentProps, - ).join(", ")}`, - doenetMLrange: { begin, end }, - displayInActivity: true, - }); - } - - let temporaryOrder = { - type: "order", - behavior: "sequence", - children: serializedDocument.children, - }; - let result = await validateOrder(temporaryOrder, activityDoenetML); - - errors.push(...result.errors); - - jsonDefinition.children = result.order.children; - - return { success: true, activityJSON: jsonDefinition, errors }; - } else { - let page = { - type: "page", - doenetML: activityDoenetML, - children: serializedComponents, - cid: activityCid, - }; - - let jsonDefinition = { - type: "activity", - children: [page], - }; - - if (documentProps.xmlns) { - if ( - documentProps.xmlns.slice(0, 34) === - "https://doenet.org/spec/doenetml/v" - ) { - jsonDefinition.version = documentProps.xmlns.slice(34); - delete documentProps.xmlns; - } else { - errors.push({ - message: `Invalid activity definition: unrecognized xmlns`, - doenetMLrange: convertDoenetMLAttrRange( - serializedDocument.attributeRanges.xmlns, - ), - displayInActivity: true, - }); - } - } else { - console.warn("no xmlns of activity!"); - } - - return { success: true, activityJSON: jsonDefinition, errors }; - } - - async function validateOrder(order, activityDoenetML) { - // Process the order object from parsing the activity definition, - // creating a new order object with - // - behavior (if in original order) - // - numberToSelect (if in original order) - // - withReplacement (if in original order) - // - children: array of pages or orders - // Returns: - // - order: the new order object - // - errors: array of any errors found - - let errors = []; - - let newOrder = { type: "order" }; - - let orderProps = {}; - for (let prop in order.props) { - let lowerProp = prop.toLowerCase(); - if (lowerProp in orderProps) { - errors.push({ - message: `duplicate attribute of : ${lowerProp}`, - doenetMLrange: convertDoenetMLAttrRange( - order.attributeRanges[prop], - ), - displayInActivity: true, - }); - } - orderProps[prop.toLowerCase()] = order.props[prop]; - } - - for (let prop in orderProps) { - if (prop === "behavior") { - newOrder.behavior = orderProps.behavior; - } else if (prop == "numbertoselect") { - newOrder.numberToSelect = Number(orderProps.numbertoselect); - } else if (prop == "withreplacement") { - newOrder.withReplacement = - orderProps.withreplacement !== undefined && - (orderProps.withreplacement === true || - orderProps.withreplacement.toLowerCase() === "true"); - } else { - errors.push({ - message: `invalid attribute: ${prop}`, - doenetMLrange: convertDoenetMLAttrRange( - order.attributeRanges[prop], - ), - displayInActivity: true, - }); - } - } - - // remove blank string children - let orderChildren = order.children.filter( - (x) => typeof x !== "string" || /\S/.test(x), - ); - - let children = []; - for (let child of orderChildren) { - if (typeof child === "string") { - errors.push({ - message: `invalid child of , found string`, - doenetMLrange: order.doenetMLrange, // just use order for now, since don't have range for string - displayInActivity: true, - }); - } else if (child.componentType.toLowerCase() === "order") { - let result = await validateOrder(child, activityDoenetML); - children.push(result.order); - errors.push(...result.errors); - } else if (child.componentType.toLowerCase() == "page") { - let result = await validatePage(child, activityDoenetML); - children.push(result.page); - errors.push(...result.errors); - } else { - errors.push({ - message: `invalid child of , found type: <${child.componentType}>`, - doenetMLrange: child.doenetMLrange, - displayInActivity: true, - }); - } - } - - newOrder.children = children; - - return { - order: newOrder, - errors, - }; - } - - async function validatePage(page, activityDoenetML) { - // Process the page object from parsing the activity definition, - // creating a new page object with - // - cid - // - doenetML: the doenetML of the page, or if children is present, - // it could be the doenetML of the entire activity, which is OK the doenetML won't be parsed in this case. - // The doenetML string needs to correspond to the doenetMLrange of children, if present, - // as snippets may be extracted (e.g,. for error messages or doenetML state variables). - // The line breaks in doenetML will also be used to calculate line numbers for user messages. - // - children (optional): the parsed children of the page. - // If not present, Core will parse the doenetML string to create the children. - // If the contents of the page were provided in the activity definition, - // we've already parsed it intot these children, - // so we send it to Core to avoid the need to parse it again. - // More importantly, we want to use the children parsed with the activity definition, - // as the line/character numbers will correspond to what the user composed. - // Returns: - // - page: the new page object - // - errors: array of any errors found - - let errors = []; - - let newPage = { type: "page" }; - - let pageProps = {}; - for (let prop in page.props) { - let lowerProp = prop.toLowerCase(); - if (lowerProp in pageProps) { - errors.push({ - message: `duplicate attribute of : ${lowerProp}`, - doenetMLrange: convertDoenetMLAttrRange( - page.attributeRanges[prop], - ), - displayInActivity: true, - }); - } - pageProps[prop.toLowerCase()] = page.props[prop]; - } - - let foundCid = false; - - for (let prop in pageProps) { - if (prop === "cid") { - newPage.cid = pageProps.cid; - delete pageProps.cid; - foundCid = true; - } else if (prop == "label") { - // we ignore label, at least for now - } else { - errors.push({ - message: `invalid attribute: ${prop}`, - doenetMLrange: convertDoenetMLAttrRange( - page.attributeRanges[prop], - ), - displayInActivity: true, - }); - } - } - - let pageChildren = removeOuterBlankStrings(page.children); - - if (foundCid) { - if (pageChildren.length > 0) { - errors.push({ - message: `Invalid page: cannot have both cid attribute and children.`, - doenetMLrange: page.doenetMLrange, - displayInActivity: true, - }); - } - try { - newPage.doenetML = await retrieveTextFileForCid( - newPage.cid, - "doenet", - ); - } catch (e) { - errors.push({ - message: `DoenetML for page with cid "${newPage.cid}" not found.`, - doenetMLrange: page.doenetMLrange, - displayInActivity: true, - }); - newPage.doenetML = ""; - } - } else if (pageChildren.length > 0) { - // the page had content inside the tags - - if ( - pageChildren.length > 1 || - pageChildren[0].componentType?.toLowerCase() !== "document" - ) { - // add document around page components - pageChildren = [ - { - componentType: "document", - children: pageChildren, - }, - ]; - - if (xmlns) { - pageChildren[0].props = { xmlns }; - } - } - - newPage.children = pageChildren; - - // Note: activityDoenetML is the doenetML of the entire activity, not the just this page. - // However, the doenetMLrange from the parser is in terms of the activityDoenetML, - // so this is the correct doenetML to use. - // Since we pass in serializedComponents, the doenetML will not be parsed or used for the page content. - newPage.doenetML = activityDoenetML; - - // To calculate the cid, however, we use doenetML of just the page - let pageDoenetML = activityDoenetML.slice( - page.doenetMLrange.openEnd, - page.doenetMLrange.closeBegin - 1, - ); - newPage.cid = await cidFromText(pageDoenetML); - } else { - // No cid and no content specified. Create a blank page. - newPage.serializedComponents = [ - { - componentType: "document", - }, - ]; - - if (xmlns) { - newPage.serializedComponents[0].props = { xmlns }; - } - - newPage.doenetML = ""; - newPage.cid = await cidFromText(newPage.doenetML); - } - - return { - page: newPage, - errors, - }; - } -} - -function removeOuterBlankStrings(serializedComponents) { - let firstNonBlankInd, lastNonBlankInd; - - // find any beginning or ending blank strings; - for (let ind = 0; ind < serializedComponents.length; ind++) { - let comp = serializedComponents[ind]; - if (typeof comp !== "string" || /\S/.test(comp)) { - if (firstNonBlankInd === undefined) { - firstNonBlankInd = ind; - } - lastNonBlankInd = ind; - } - } - - serializedComponents = serializedComponents.slice( - firstNonBlankInd, - lastNonBlankInd + 1, - ); - - return serializedComponents; -} - -export async function calculateOrderAndVariants({ - activityDefinition, - requestedVariantIndex, - flags = {}, -}) { - let errors = []; - - let activityVariantResult = await determineNumberOfActivityVariants( - activityDefinition, - flags, - ); - - let variantIndex = - ((requestedVariantIndex - 1) % activityVariantResult.numVariants) + 1; - if (variantIndex < 1) { - variantIndex += activityVariantResult.numVariants; - } - - if (!Number.isFinite(variantIndex)) { - errors.push({ - message: "Invalid requested variant index", - displayInActivity: true, - }); - variantIndex = 1; - } - - let rng = new rngClass(variantIndex.toString()); - - let activityPages = []; - - for (let item of activityDefinition.children) { - let type = item.type.toLowerCase(); - if (type === "page") { - activityPages.push(item); - } else if (type === "order") { - let orderResult = determineOrder(item, rng); - errors.push(...orderResult.errors); - activityPages.push(...orderResult.pages); - } else { - errors.push({ - message: `Unrecognized item <${item.type}> in activity.`, - doenetMLrange: item.doenetMLrange, - displayInActivity: true, - }); - } - } - - let itemWeights = activityDefinition.itemWeights || []; - - if (!Array.isArray(itemWeights) || !itemWeights.every((x) => x >= 0)) { - errors.push({ - message: "Invalid itemWeights", - displayInActivity: true, - }); - itemWeights = []; - } - - let nPages = activityPages.length; - - itemWeights = itemWeights.slice(0, nPages); - - if (itemWeights.length < nPages) { - itemWeights.push(...Array(nPages - itemWeights.length).fill(1)); - } - - // normalize itemWeights to sum to 1 - let totalWeight = itemWeights.reduce((a, c) => a + c); - if (totalWeight > 0) { - itemWeights = itemWeights.map((x) => x / totalWeight); - } - - let pageVariantsResult; - let pageCoreWorkersInfo = []; - - if (activityVariantResult.pageVariantsResult) { - pageVariantsResult = activityVariantResult.pageVariantsResult; - pageCoreWorkersInfo = activityVariantResult.pageCoreWorkersInfo; - } else { - let promises = []; - pageVariantsResult = []; - for (let page of activityPages) { - let coreWorker = createCoreWorker(); - let theInfo = { - coreWorker, - doenetML: page.doenetML, - preliminarySerializedComponents: page.children, - flags, - }; - pageCoreWorkersInfo.push(theInfo); - promises.push( - initializeCoreWorker(theInfo).then(() => { - return returnAllPossibleVariantsFromCoreWorker(coreWorker); - }), - ); - } - - // use allSettled to make sure all initializations are run - let promiseResults = await Promise.allSettled(promises); - - for (let result of promiseResults) { - if (result.status === "fulfilled") { - pageVariantsResult.push(result.value); - } else { - pageVariantsResult.push(["a"]); - errors.push({ - message: `Error initializing activity. ${result.reason}`, - displayInActivity: true, - }); - } - } - } - - let variantsByPage; - - let allPossiblePerPage = []; - let numVariantsPerPage = []; - - for (let possibleVariants of pageVariantsResult) { - allPossiblePerPage.push(possibleVariants); - numVariantsPerPage.push(possibleVariants.length); - } - - let numberOfPageVariantCombinations = numVariantsPerPage.reduce( - (a, c) => a * c, - 1, - ); - - if (numberOfPageVariantCombinations <= activityVariantResult.numVariants) { - let pageVariantCombinationIndex = - ((variantIndex - 1) % numberOfPageVariantCombinations) + 1; - - variantsByPage = enumerateCombinations({ - numberOfOptionsByIndex: numVariantsPerPage, - maxNumber: pageVariantCombinationIndex, - })[pageVariantCombinationIndex - 1].map((x) => x + 1); - } else { - variantsByPage = [...Array(nPages).keys()].map( - (i) => Math.floor(rng() * numVariantsPerPage[i]) + 1, - ); - } - - let previousComponentTypeCounts = - await initializeComponentTypeCounts(pageCoreWorkersInfo); - - let activityInfo = { - activityPages, - variantsByPage, - itemWeights, - numVariants: activityVariantResult.numVariants, - previousComponentTypeCounts, - }; - - return { - errors, - order: activityPages, - itemWeights, - variantsByPage, - variantIndex, - activityInfo, - previousComponentTypeCounts, - pageVariantsResult, - pageCoreWorkersInfo, - }; -} - -export async function determineNumberOfActivityVariants( - activityDefinition, - flags, -) { - // Number of variants is numVariants for activity definition or 1000, - // with one exception that also has additional side effects. - // If numVariants is not specified and the activity definition has only pages (no orders), - // then spin up a core worker for each page - // and use it to calculate the number of variants for each page. - // The number of variants for the activity is the product of variants for each page - // (capped at 1000, currently not adjustable). - // In this case, return the core workers and the variant results - // to reduce duplicate calculations later. - - let numVariants = 1000; - let pageVariantsResult = null; - let pageCoreWorkersInfo = []; - - if (activityDefinition.numVariants !== undefined) { - numVariants = activityDefinition.numVariants; - if (!(Number.isInteger(numVariants) && numVariants >= 1)) { - numVariants = 1000; - } - } else if (activityDefinition.children.every((x) => x.type === "page")) { - // determine number of variants from the pages - - let promises = []; - for (let page of activityDefinition.children) { - let coreWorker = createCoreWorker(); - let theInfo = { - coreWorker, - doenetML: page.doenetML, - preliminarySerializedComponents: page.children, - flags, - }; - pageCoreWorkersInfo.push(theInfo); - promises.push( - initializeCoreWorker(theInfo).then(() => { - return returnAllPossibleVariantsFromCoreWorker(coreWorker); - }), - ); - } - - try { - pageVariantsResult = await Promise.all(promises); - numVariants = pageVariantsResult.reduce((a, c) => a * c.length, 1); - numVariants = Math.min(1000, numVariants); - } catch (e) {} - } - - return { numVariants, pageVariantsResult, pageCoreWorkersInfo }; -} - -export function createCoreWorker() { - return new Worker(doenetGlobalConfig.doenetWorkerUrl, { - type: "classic", - }); -} - -export function initializeCoreWorker({ - coreWorker, - doenetML, - preliminarySerializedComponents, - flags, -}) { - // Initializes core worker with the given arguments. - // Returns a promise. - // If the worker is successfully initialized, the promise is resolved - // If an error was encountered while initializing, the promise is rejected - - let resolveInitializePromise; - let rejectInitializePromise; - - let initializePromise = new Promise((resolve, reject) => { - resolveInitializePromise = resolve; - rejectInitializePromise = reject; - }); - - let initializeListener = function (e) { - if (e.data.messageType === "initializeResult") { - coreWorker.removeEventListener("message", initializeListener); - - let initializeResult = e.data.args; - - if (initializeResult.success) { - resolveInitializePromise(); - } else { - rejectInitializePromise(new Error(initializeResult.errMsg)); - } - } - }; - - coreWorker.addEventListener("message", initializeListener); - - coreWorker.postMessage({ - messageType: "initializeWorker", - args: { - doenetML, - preliminarySerializedComponents, - flags, - }, - }); - - return initializePromise; -} - -export async function createAndInitializePageCoreWorkers(activityPages, flags) { - let promises = []; - let pageCoreWorkersInfo = []; - let errors = []; - - for (let page of activityPages) { - let coreWorker = createCoreWorker(); - - let theInfo = { - coreWorker, - doenetML: page.doenetML, - preliminarySerializedComponents: page.children, - flags, - }; - - pageCoreWorkersInfo.push(theInfo); - promises.push(initializeCoreWorker(theInfo)); - } - - // use allSettled to make sure all initializations are run - let promiseResults = await Promise.allSettled(promises); - - for (let result of promiseResults) { - if (result.status === "rejected") { - errors.push({ - message: `Error initializing activity. ${result.reason}`, - displayInActivity: true, - }); - } - } - - return { pageCoreWorkersInfo, errors }; -} - -export function returnAllPossibleVariantsFromCoreWorker(coreWorker) { - // calculate all possible variants from an initialized core worker - // returns promise - // If the worker was already initialized, - // then the promise resolves to the allPossibleVariants object - // If the worker was not already initialized, then the promise is rejected - - let resolveAllPossibleVariantsPromise; - let rejectAllPossibleVariantsPromise; - - let allPossibleVariantsPromise = new Promise((resolve, reject) => { - resolveAllPossibleVariantsPromise = resolve; - rejectAllPossibleVariantsPromise = reject; - }); - - let allPossibleVariantsListener = function (e) { - if (e.data.messageType === "allPossibleVariants") { - let allPossibleVariantsResult = e.data.args; - - coreWorker.removeEventListener( - "message", - allPossibleVariantsListener, - ); - - if (allPossibleVariantsResult.success) { - resolveAllPossibleVariantsPromise( - allPossibleVariantsResult.allPossibleVariants, - ); - } else { - rejectAllPossibleVariantsPromise(); - } - } - }; - - coreWorker.addEventListener("message", allPossibleVariantsListener); - - coreWorker.postMessage({ - messageType: "returnAllPossibleVariants", - }); - - return allPossibleVariantsPromise; -} - -export async function returnNumberOfActivityVariantsForCid(cid) { - let activityDefinitionDoenetML = await retrieveTextFileForCid(cid); - - let result = await parseActivityDefinition(activityDefinitionDoenetML); - - let errors = result.errors; - - result = await determineNumberOfActivityVariants(result.activityJSON); - - return { - numVariants: result.numVariants, - pageVariantsResult: result.pageVariantsResult, - errors, - }; -} - -function determineOrder(order, rng) { - if (order?.type?.toLowerCase() !== "order") { - return { success: false, message: "invalid order" }; - } - - let behavior = order.behavior?.toLowerCase(); - - if (behavior === undefined) { - behavior = "sequence"; - } - - switch (behavior) { - case "sequence": - return processSequenceOrder(order, rng); - case "select": - return processSelectOrder(order, rng); - case "shuffle": - return processShuffleOrder(order, rng); - default: - return { - success: false, - message: `Have not implemented behavior: ${behavior}`, - }; - } -} - -function processSequenceOrder(order, rng) { - let pages = []; - let errors = []; - - for (let item of order.children) { - let type = item.type.toLowerCase(); - if (type === "page") { - pages.push(item); - } else if (type === "order") { - let orderResult = determineOrder(item, rng); - errors.push(...orderResult.errors); - pages.push(...orderResult.pages); - } else { - errors.push({ - message: `Unrecognized item <${item.type}> in order.`, - doenetMLrange: item.doenetMLrange, - displayInActivity: true, - }); - } - } - - return { pages, errors }; -} - -function processSelectOrder(order, rng) { - let numberToSelect = order.numberToSelect; - let nItems = order.children.length; - let errors = []; - - if (!(Number.isInteger(numberToSelect) && numberToSelect > 0)) { - numberToSelect = 1; - } - - let numberUniqueRequired = 1; - if (!order.withReplacement) { - numberUniqueRequired = numberToSelect; - } - - if (numberUniqueRequired > nItems) { - errors.push({ - message: - "Cannot select " + - numberUniqueRequired + - " components from only " + - nItems, - doenetMLrange: order.doenetMLrange, - displayInActivity: true, - }); - return { - pages: [], - errors, - }; - } - - let selectWeights = order.selectWeights || []; - - if (!Array.isArray(selectWeights) || !selectWeights.every((x) => x >= 0)) { - errors.push({ - message: "Invalid selectWeights", - doenetMLrange: order.doenetMLrange, - displayInActivity: true, - }); - } - - selectWeights = selectWeights.slice(0, nItems); - - if (selectWeights.length < nItems) { - selectWeights.push(...Array(nItems - selectWeights.length).fill(1)); - } - - // normalize selectWeights to sum to 1 - let totalWeight = selectWeights.reduce((a, c) => a + c); - selectWeights = selectWeights.map((x) => x / totalWeight); - - //https://stackoverflow.com/a/44081700 - let cumulativeWeights = selectWeights.reduce( - (a, x, i) => [...a, x + (a[i - 1] || 0)], - [], - ); - let indsRemaining = [...Array(cumulativeWeights.length).keys()]; - - let selectedItems = []; - - for (let ind = 0; ind < numberToSelect; ind++) { - // random number in [0, 1) - let rand = rng(); - - // find largest index where cumulativeWeight is larger than rand - // using binary search - let start = -1, - end = cumulativeWeights.length - 1; - while (start < end - 1) { - let mid = Math.floor((start + end) / 2); // mid point - if (cumulativeWeights[mid] > rand) { - end = mid; - } else { - start = mid; - } - } - - selectedItems.push(order.children[indsRemaining[end]]); - - if (!order.withReplacement && ind < numberToSelect - 1) { - // remove selected index and renormalize weights - selectWeights.splice(end, 1); - indsRemaining.splice(end, 1); - totalWeight = selectWeights.reduce((a, c) => a + c); - selectWeights = selectWeights.map((x) => x / totalWeight); - cumulativeWeights = selectWeights.reduce( - (a, x, i) => [...a, x + (a[i - 1] || 0)], - [], - ); - } - } - - let pages = []; - - for (let item of selectedItems) { - let type = item.type.toLowerCase(); - if (type === "page") { - pages.push(item); - } else if (type === "order") { - let orderResult = determineOrder(item); - pages.push(...orderResult.pages); - errors.push(...orderResult.errors); - } else { - errors.push({ - message: `Unrecognized item ${item.type} in order`, - doenetMLrange: item.doenetMLrange, - displayInActivity: true, - }); - } - } - - return { pages, errors }; -} - -function processShuffleOrder(order, rng) { - let newOrder = [...order.children]; - let errors = []; - - // shuffle the order - // https://stackoverflow.com/a/12646864 - for (let i = order.children.length - 1; i > 0; i--) { - const rand = rng(); - const j = Math.floor(rand * (i + 1)); - [newOrder[i], newOrder[j]] = [newOrder[j], newOrder[i]]; - } - - let pages = []; - - for (let item of newOrder) { - let type = item.type.toLowerCase(); - if (type === "page") { - pages.push(item); - } else if (type === "order") { - let orderResult = determineOrder(item, rng); - pages.push(...orderResult.pages); - errors.push(...orderResult.errors); - } else { - errors.push({ - message: `Unrecognized item ${item.type} in order`, - doenetMLrange: item.doenetMLrange, - displayInActivity: true, - }); - } - } - - return { pages, errors }; -} - -async function returnComponentTypeCounts(coreWorker) { - // Returns a promise. - // If successfully obtain counts, the promise is resolved with those counts. - // If an error was encountered, the promise is rejected - - let resolveCountPromise; - let rejectCountPromise; - - let countPromise = new Promise((resolve, reject) => { - resolveCountPromise = resolve; - rejectCountPromise = reject; - }); - - let componentCountListener = function (e) { - if (e.data.messageType === "componentTypeCounts") { - coreWorker.removeEventListener("message", componentCountListener); - - let countResult = e.data.args; - - if (countResult.success) { - resolveCountPromise(countResult.componentTypeCounts); - } else { - rejectCountPromise(); - } - } - }; - - coreWorker.addEventListener("message", componentCountListener); - - coreWorker.postMessage({ - messageType: "returnComponentCounts", - }); - - return countPromise; -} - -async function initializeComponentTypeCounts(pageCoreWorkersInfo) { - let previousComponentTypeCountsByPage = [{}]; - - let promises = []; - - for (let coreWorkerInfo of pageCoreWorkersInfo.slice( - 0, - pageCoreWorkersInfo.length - 1, - )) { - promises.push(returnComponentTypeCounts(coreWorkerInfo.coreWorker)); - } - - try { - let allComponentCounts = await Promise.all(promises); - - for (let [ind, componentTypeCounts] of allComponentCounts.entries()) { - let countsSoFar = previousComponentTypeCountsByPage[ind]; - for (let cType in countsSoFar) { - if (cType in componentTypeCounts) { - componentTypeCounts[cType] += countsSoFar[cType]; - } else { - componentTypeCounts[cType] = countsSoFar[cType]; - } - } - - previousComponentTypeCountsByPage.push(componentTypeCounts); - } - } catch (e) {} - - return previousComponentTypeCountsByPage; -} - -export function normalizeErrors(errors, doenetML) { - if (errors.length > 0) { - let doenetMLNewlines = findAllNewlines(doenetML); - for (let err of errors) { - if ( - err.doenetMLrange && - err.doenetMLrange.lineBegin === undefined - ) { - Object.assign( - err.doenetMLrange, - getLineCharRange(err.doenetMLrange, doenetMLNewlines), - ); - } - } - } - - return errors; -} diff --git a/packages/doenetml/src/utils/activtyWebWorker.js b/packages/doenetml/src/utils/activtyWebWorker.js deleted file mode 100644 index 3070145e8..000000000 --- a/packages/doenetml/src/utils/activtyWebWorker.js +++ /dev/null @@ -1,27 +0,0 @@ -export function prerenderActivity({ cid, doenetId, flags }) { - // TODO - do we need to move this web worker to an iife as well? - // see - https://github.com/Doenet/DoenetML/pull/69 - let worker = new Worker("/utils/prerenderWorker.js", { type: "module" }); - - // console.log(`Prerendering activity`, cid, doenetId, flags, worker); - - worker.postMessage({ - messageType: "prerenderActivity", - args: { - cid, - doenetId, - flags, - }, - }); - - worker.onmessage = function (e) { - if (e.data.messageType === "finished") { - worker.terminate(); - } else if (e.data.messageType === "error") { - console.error(e.data.message); - worker.terminate(); - } - }; - - return worker; -} diff --git a/packages/doenetml/src/utils/pageUtils.js b/packages/doenetml/src/utils/pageUtils.js new file mode 100644 index 000000000..64ab1fc1d --- /dev/null +++ b/packages/doenetml/src/utils/pageUtils.js @@ -0,0 +1,48 @@ +import { doenetGlobalConfig } from "../global-config"; + +export function createCoreWorker() { + return new Worker(doenetGlobalConfig.doenetWorkerUrl, { + type: "classic", + }); +} + +export function initializeCoreWorker({ coreWorker, doenetML, flags }) { + // Initializes core worker with the given arguments. + // Returns a promise. + // If the worker is successfully initialized, the promise is resolved + // If an error was encountered while initializing, the promise is rejected + + let resolveInitializePromise; + let rejectInitializePromise; + + let initializePromise = new Promise((resolve, reject) => { + resolveInitializePromise = resolve; + rejectInitializePromise = reject; + }); + + let initializeListener = function (e) { + if (e.data.messageType === "initializeResult") { + coreWorker.removeEventListener("message", initializeListener); + + let initializeResult = e.data.args; + + if (initializeResult.success) { + resolveInitializePromise(); + } else { + rejectInitializePromise(new Error(initializeResult.errMsg)); + } + } + }; + + coreWorker.addEventListener("message", initializeListener); + + coreWorker.postMessage({ + messageType: "initializeWorker", + args: { + doenetML, + flags, + }, + }); + + return initializePromise; +} diff --git a/packages/doenetml/src/utils/prerenderWorker.js b/packages/doenetml/src/utils/prerenderWorker.js deleted file mode 100644 index 2e8b9cfa4..000000000 --- a/packages/doenetml/src/utils/prerenderWorker.js +++ /dev/null @@ -1,267 +0,0 @@ -import axios from "axios"; -import { - retrieveTextFileForCid, - serializedComponentsReplacer, -} from "@doenet/utils"; -import { - calculateOrderAndVariants, - determineNumberOfActivityVariants, - parseActivityDefinition, -} from "./activityUtils"; -import { doenetGlobalConfig } from "../global-config"; - -onmessage = function (e) { - if (e.data.messageType === "prerenderActivity") { - prerenderActivity(e.data.args); - } -}; - -async function prerenderActivity({ cid, doenetId, flags = {} }) { - let activityDefDoenetML; - - try { - activityDefDoenetML = await retrieveTextFileForCid(cid, "doenet"); - } catch (e) { - postMessage({ messageType: "error", message: e.message }); - return; - } - - let parseResult = await parseActivityDefinition(activityDefDoenetML, cid); - - // TODO: handle error display better - if (parseResult.errors.length > 0) { - postMessage({ - messageType: "error", - message: parseResult.errors[0].message, - }); - return; - } - - let activityDefinition = parseResult.activityJSON; - - let { numVariants } = - await determineNumberOfActivityVariants(activityDefinition); - - postMessage({ messageType: "status", stage: "gathering", complete: 0 }); - - // first determine all the pages and the variant indices needed for each page - - const variantsNeededByPage = {}; - const doenetMLByPage = {}; - - for (let variantIndex = 1; variantIndex <= numVariants; variantIndex++) { - console.log(`Gathering ${variantIndex} of ${numVariants}`); - - let result = await calculateOrderAndVariants({ - activityDefinition, - requestedVariantIndex: variantIndex, - }); - - if (result.errors.length > 0) { - console.error( - `Couldn't save initial renderer state: ${result.message}`, - ); - continue; - } - - let order = result.order; - let variantsByPage = result.variantsByPage; - - for (let [pageInd, page] of order.entries()) { - let variantsNeeded = variantsNeededByPage[page.cid]; - if (!variantsNeeded) { - variantsNeeded = variantsNeededByPage[page.cid] = []; - } - - let pageVariant = variantsByPage[pageInd]; - if (!variantsNeeded.includes(pageVariant)) { - variantsNeeded.push(pageVariant); - } - - doenetMLByPage[page.cid] = page.doenetML; - } - - if (variantIndex % 10 === 0) { - postMessage({ - messageType: "status", - stage: "Gathering", - complete: variantIndex / numVariants, - }); - } - } - - postMessage({ messageType: "status", stage: "Gathering", complete: 1 }); - - let allCids = Object.keys(variantsNeededByPage); - - let payload = { - doenetId, - cids: allCids, - showCorrectness: flags.showCorrectness, - solutionDisplayMode: flags.solutionDisplayMode, - showFeedback: flags.showFeedback, - showHints: flags.showHints, - autoSubmit: flags.autoSubmit, - }; - - let { data } = await axios.post( - "/api/getSavedInitialRendererStates.php", - payload, - ); - - if (!data.success) { - console.error("Count not retrieve saved initial renderer states"); - } else { - let foundVariants = data.foundVariants; - - for (let [ind, cid] of allCids.entries()) { - let variantsNeeded = variantsNeededByPage[cid]; - for (let variant of foundVariants[ind]) { - let varInd = variantsNeeded.indexOf(Number(variant)); - - if (varInd !== -1) { - variantsNeeded.splice(varInd, 1); - if (variantsNeeded.length === 0) { - delete variantsNeededByPage[cid]; - } - } - } - } - } - - let totalnumVariants = Object.values(variantsNeededByPage).reduce( - (a, c) => a + c.length, - 0, - ); - - let nFinished = 0; - - postMessage({ messageType: "status", stage: "Rendering", complete: 0 }); - - for (let cid in variantsNeededByPage) { - console.log(`prerendering page with cid: ${cid}`); - - let doenetML = doenetMLByPage[cid]; - - for (let requestedVariantIndex of variantsNeededByPage[cid]) { - let { coreInfo, rendererState } = - await calculateInitialRendererState({ - doenetML, - doenetId, - requestedVariantIndex, - flags, - }); - console.log(`variant ${requestedVariantIndex} prerendered`); - - let payload = { - doenetId, - cid, - variantIndex: requestedVariantIndex, - showCorrectness: flags.showCorrectness, - solutionDisplayMode: flags.solutionDisplayMode, - showFeedback: flags.showFeedback, - showHints: flags.showHints, - autoSubmit: flags.autoSubmit, - rendererState: JSON.stringify( - rendererState, - serializedComponentsReplacer, - ), - coreInfo: JSON.stringify( - coreInfo, - serializedComponentsReplacer, - ), - }; - - try { - let resp = await axios.post( - "/api/saveInitialRendererState.php", - payload, - ); - - if (!resp.data.success) { - console.error( - `Couldn't save initial renderer state: ${resp.data.message}`, - ); - } else if (resp.data.message) { - console.log( - `Initial renderer state not saved: ${resp.data.message}`, - ); - } - } catch (e) { - console.error( - `Couldn't save initial renderer state: ${e.message}`, - ); - } - - nFinished++; - postMessage({ - messageType: "status", - stage: "Rendering", - complete: nFinished / totalnumVariants, - }); - console.log( - `progress rendering: ${Math.round( - (nFinished / totalnumVariants) * 100, - )}%`, - ); - } - } - - postMessage({ messageType: "finished" }); -} - -function calculateInitialRendererState({ - doenetML, - doenetId, - requestedVariantIndex, - flags = {}, -}) { - let coreWorker = new Worker(doenetGlobalConfig.doenetWorkerUrl, { - type: "classic", - }); - - coreWorker.postMessage({ - messageType: "createCore", - args: { - doenetML, - doenetId, - requestedVariantIndex, - flags, - prerender: true, - }, - }); - - let resolveRenderState; - let rendererStatePromise = new Promise((resolve, reject) => { - resolveRenderState = resolve; - }); - - let rendererState = {}; - coreWorker.onmessage = function (e) { - // console.log('message from core', e.data) - if (e.data.messageType === "updateRenderers" && e.data.init) { - for (let instruction of e.data.args.updateInstructions) { - if (instruction.instructionType === "updateRendererStates") { - for (let { - componentName, - stateValues, - childrenInstructions, - } of instruction.rendererStatesToUpdate) { - rendererState[componentName] = { - stateValues, - childrenInstructions, - }; - } - } - } - } else if (e.data.messageType === "initializeRenderers") { - let coreInfo = e.data.args.coreInfo; - - coreWorker.terminate(); - - resolveRenderState({ coreInfo, rendererState }); - } - }; - - return rendererStatePromise; -} diff --git a/packages/standalone/package.json b/packages/standalone/package.json index 52b877a33..14ef1e0d6 100644 --- a/packages/standalone/package.json +++ b/packages/standalone/package.json @@ -2,7 +2,7 @@ "name": "@doenet/standalone", "type": "module", "description": "Standalone renderer for DoenetML suitable for being included in a web page", - "version": "0.7.0-alpha21", + "version": "0.7.0-alpha23", "license": "AGPL-3.0-or-later", "homepage": "https://github.com/Doenet/DoenetML#readme", "private": true, diff --git a/packages/test-cypress/cypress/e2e/ActivityViewer/activityVariants.cy.js b/packages/test-cypress/cypress/e2e/ActivityViewer/activityVariants.cy.js deleted file mode 100644 index 9ce3e0cf8..000000000 --- a/packages/test-cypress/cypress/e2e/ActivityViewer/activityVariants.cy.js +++ /dev/null @@ -1,1817 +0,0 @@ -import { cesc, cesc2, numberToLetters } from "@doenet/utils"; - -describe("Activity variants tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("Variants from single page, no variant control in page", () => { - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_allowLocalState").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - let doenetML; - - let attemptNumber = 0; - - for (let ind = 1; ind <= 200; ind += 97) { - cy.window().then(async (win) => { - attemptNumber++; - doenetML = ` - - - ${attemptNumber} - Enter : - $n - - - `; - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - attemptNumber, - }, - "*", - ); - cy.get(cesc("#\\/_text1")).should( - "have.text", - `${attemptNumber}`, - ); - }); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 100) + 1); - expect(activityData.variantsByPage).eqls([ - ((ind - 1) % 100) + 1, - ]); - - let stateVariables = await win.returnAllStateVariables1(); - let n = stateVariables["/n"].stateValues.value; - - expect(n).gte(1); - expect(n).lte(1000); - - let mathinputName = cesc2( - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName, - ); - let mathinputAnchor = "#" + mathinputName + " textarea"; - let mathinputEditiableFieldAnchor = - "#" + mathinputName + " .mq-editable-field"; - let mathinputSubmitAnchor = "#" + mathinputName + "_submit"; - let mathinputCorrectAnchor = "#" + mathinputName + "_correct"; - let mathinputIncorrectAnchor = - "#" + mathinputName + "_incorrect"; - - cy.get(mathinputAnchor).type(`${n}{enter}`, { force: true }); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - }); - - cy.wait(2000); // wait for 1 second debounce - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - attemptNumber, - }, - "*", - ); - cy.get(cesc("#\\/_text1")).should( - "have.text", - `${attemptNumber}`, - ); - }); - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = - await win.returnAllStateVariables1(); - return stateVariables["/_answer1"]; - }), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - }); - - cy.get(mathinputAnchor).type(`{end}1`, { force: true }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.get(mathinputAnchor).type(`{end}{backspace}`, { - force: true, - }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("be.visible"); - }); - } - }); - - it("Variants from single page, specified variants in page", () => { - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_allowLocalState").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - let doenetML = ` - - - - a - Enter - - : - $color - - - `; - - for (let ind = 1; ind <= 4; ind++) { - if (ind > 1) { - cy.reload(); - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_newAttempt").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let color = ["red", "blue", "green"][(ind - 1) % 3]; - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 3) + 1); - expect(activityData.variantsByPage).eqls([((ind - 1) % 3) + 1]); - - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/color"].replacements[0]).eq(color); - - let textinputName = cesc2( - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName, - ); - let textinputAnchor = "#" + textinputName + "_input"; - let textinputSubmitAnchor = "#" + textinputName + "_submit"; - let textinputCorrectAnchor = "#" + textinputName + "_correct"; - let textinputIncorrectAnchor = - "#" + textinputName + "_incorrect"; - - cy.get(textinputAnchor).type(`${color}{enter}`); - cy.get(textinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - }); - - cy.wait(2000); // wait for 1 second debounce - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = - await win.returnAllStateVariables1(); - return stateVariables["/_answer1"]; - }), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - }); - - cy.get(textinputAnchor).type(`{end}x`); - cy.get(textinputSubmitAnchor).click(); - cy.get(textinputIncorrectAnchor).should("be.visible"); - - cy.get(textinputAnchor).type(`{end}{backspace}`); - cy.get(textinputSubmitAnchor).click(); - cy.get(textinputCorrectAnchor).should("be.visible"); - }); - } - }); - - it("Variants from single page, specified variants in problem in page", () => { - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_allowLocalState").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - let doenetML = ` - - - - - a - Enter - - : - $color - - - - `; - - for (let ind = 1; ind <= 4; ind++) { - if (ind > 1) { - cy.reload(); - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_newAttempt").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let color = ["red", "blue", "green"][(ind - 1) % 3]; - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 3) + 1); - expect(activityData.variantsByPage).eqls([((ind - 1) % 3) + 1]); - - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/color"].replacements[0]).eq(color); - - let textinputName = cesc2( - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName, - ); - let textinputAnchor = "#" + textinputName + "_input"; - let textinputSubmitAnchor = "#" + textinputName + "_submit"; - let textinputCorrectAnchor = "#" + textinputName + "_correct"; - let textinputIncorrectAnchor = - "#" + textinputName + "_incorrect"; - - cy.get(textinputAnchor).type(`${color}{enter}`); - cy.get(textinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - }); - - cy.wait(2000); // wait for 1 second debounce - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = - await win.returnAllStateVariables1(); - return stateVariables["/_answer1"]; - }), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_answer1"].stateValues.creditAchieved, - ).eq(1); - }); - - cy.get(textinputAnchor).type(`{end}x`); - cy.get(textinputSubmitAnchor).click(); - cy.get(textinputIncorrectAnchor).should("be.visible"); - - cy.get(textinputAnchor).type(`{end}{backspace}`); - cy.get(textinputSubmitAnchor).click(); - cy.get(textinputCorrectAnchor).should("be.visible"); - }); - } - }); - - it("Two pages few variants, page variants enumerated", () => { - let doenetML = ` - - - a - - - - - b - - - - - `; - - for (let ind = 1; ind <= 2000; ind += 371) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - activityData.variantsByPage[0], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - numberToLetters(activityData.variantsByPage[1], true), - ); - }); - }); - } - }); - - it("Two pages, numVariants not specified, defaults to 1000", () => { - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_allowLocalState").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - let doenetML = ` - - - a - Enter : - $n - - - b - - Enter : - $l - - - `; - - for (let ind = 1; ind <= 2000; ind += 970) { - if (ind > 1) { - cy.reload(); - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_newAttempt").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 1000) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).gte(1); - expect(activityData.variantsByPage[0]).lte(100); - expect(activityData.variantsByPage[1]).gte(1); - expect(activityData.variantsByPage[1]).lte(26); - - let l = numberToLetters(activityData.variantsByPage[1], true); - - let stateVariables1 = await win.returnAllStateVariables1(); - let n = stateVariables1["/n"].stateValues.value; - - expect(n).gte(1); - expect(n).lte(1000); - - let mathinputName = cesc2( - stateVariables1["/_answer1"].stateValues.inputChildren[0] - .componentName, - ); - let mathinputAnchor = "#page1" + mathinputName + " textarea"; - let mathinputEditiableFieldAnchor = - "#page1" + mathinputName + " .mq-editable-field"; - let mathinputSubmitAnchor = - "#page1" + mathinputName + "_submit"; - let mathinputCorrectAnchor = - "#page1" + mathinputName + "_correct"; - let mathinputIncorrectAnchor = - "#page1" + mathinputName + "_incorrect"; - - cy.get(mathinputAnchor).type(`${n}{enter}`, { force: true }); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables1 = await win.returnAllStateVariables1(); - expect( - stateVariables1["/_answer1"].stateValues.creditAchieved, - ).eq(1); - }); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq(l); - - let textinputName = cesc2( - stateVariables2["/_answer1"].stateValues - .inputChildren[0].componentName, - ); - let textinputAnchor = "#page2" + textinputName + "_input"; - let textinputSubmitAnchor = - "#page2" + textinputName + "_submit"; - let textinputCorrectAnchor = - "#page2" + textinputName + "_correct"; - let textinputIncorrectAnchor = - "#page2" + textinputName + "_incorrect"; - - cy.get(textinputAnchor).type(`${l}{enter}`); - cy.get(textinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables2 = - await win.returnAllStateVariables2(); - expect( - stateVariables2["/_answer1"].stateValues - .creditAchieved, - ).eq(1); - }); - - cy.get("[data-test=previous]").click(); - - cy.get(mathinputEditiableFieldAnchor).should( - "have.text", - `${n}`, - ); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.get("[data-test=next]").click(); - - cy.get(textinputAnchor).should("have.value", l); - cy.get(textinputCorrectAnchor).should("be.visible"); - - cy.wait(2000); // wait for 1 second debounce - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables2 = - await win.returnAllStateVariables2(); - return stateVariables2["/_answer1"]; - }), - ); - - cy.window().then(async (win) => { - let stateVariables2 = - await win.returnAllStateVariables2(); - expect( - stateVariables2["/_answer1"].stateValues - .creditAchieved, - ).eq(1); - }); - - cy.get(textinputAnchor).type(`{end}X`); - cy.get(textinputSubmitAnchor).click(); - cy.get(textinputIncorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables2 = - await win.returnAllStateVariables2(); - expect( - stateVariables2["/_answer1"].stateValues - .creditAchieved, - ).eq(0); - }); - - cy.get("[data-test=previous]").click(); - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables1 = - await win.returnAllStateVariables1(); - return stateVariables1["/_answer1"]; - }), - ); - - cy.window().then(async (win) => { - let stateVariables1 = - await win.returnAllStateVariables1(); - expect( - stateVariables1["/_answer1"].stateValues - .creditAchieved, - ).eq(1); - }); - - cy.get(mathinputAnchor).type(`{end}1`, { force: true }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables1 = - await win.returnAllStateVariables1(); - expect( - stateVariables1["/_answer1"].stateValues - .creditAchieved, - ).eq(0); - }); - - cy.get("[data-test=next]").click(); - - cy.get(textinputAnchor).type(`{end}{backspace}`); - cy.get(textinputSubmitAnchor).click(); - cy.get(textinputCorrectAnchor).should("be.visible"); - - cy.get("[data-test=previous]").click(); - - cy.get(mathinputAnchor).type(`{end}{backspace}`, { - force: true, - }); - cy.get(mathinputSubmitAnchor).click(); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables1 = - await win.returnAllStateVariables1(); - expect( - stateVariables1["/_answer1"].stateValues - .creditAchieved, - ).eq(1); - let stateVariables2 = - await win.returnAllStateVariables2(); - expect( - stateVariables2["/_answer1"].stateValues - .creditAchieved, - ).eq(1); - }); - }); - }); - } - }); - - it("Two pages, specify numVariants is 2", () => { - let doenetML = ` - - - a - Enter : - $n - - - b - - Enter : - $l - - - `; - - let numbers = []; - let letters = []; - - for (let ind = 1; ind <= 3; ind++) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 2) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).gte(1); - expect(activityData.variantsByPage[0]).lte(100); - expect(activityData.variantsByPage[1]).gte(1); - expect(activityData.variantsByPage[1]).lte(26); - - let l = numberToLetters(activityData.variantsByPage[1], true); - - if (letters[activityData.variantIndex] === undefined) { - letters[activityData.variantIndex] = l; - } else { - expect(l).eq(letters[activityData.variantIndex]); - } - - let stateVariables1 = await win.returnAllStateVariables1(); - let n = stateVariables1["/n"].stateValues.value; - - if (numbers[activityData.variantIndex] === undefined) { - numbers[activityData.variantIndex] = n; - } else { - expect(n).eq(numbers[activityData.variantIndex]); - } - - let mathinputName = cesc2( - stateVariables1["/_answer1"].stateValues.inputChildren[0] - .componentName, - ); - let mathinputAnchor = "#page1" + mathinputName + " textarea"; - let mathinputEditiableFieldAnchor = - "#page1" + mathinputName + " .mq-editable-field"; - let mathinputSubmitAnchor = - "#page1" + mathinputName + "_submit"; - let mathinputCorrectAnchor = - "#page1" + mathinputName + "_correct"; - let mathinputIncorrectAnchor = - "#page1" + mathinputName + "_incorrect"; - - cy.get(mathinputAnchor).type(`${n}{enter}`, { force: true }); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables1 = await win.returnAllStateVariables1(); - expect( - stateVariables1["/_answer1"].stateValues.creditAchieved, - ).eq(1); - }); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq(l); - - let textinputName = cesc2( - stateVariables2["/_answer1"].stateValues - .inputChildren[0].componentName, - ); - let textinputAnchor = "#page2" + textinputName + "_input"; - let textinputSubmitAnchor = - "#page2" + textinputName + "_submit"; - let textinputCorrectAnchor = - "#page2" + textinputName + "_correct"; - let textinputIncorrectAnchor = - "#page2" + textinputName + "_incorrect"; - - cy.get(textinputAnchor).type(`${l}{enter}`); - cy.get(textinputCorrectAnchor).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables2 = - await win.returnAllStateVariables2(); - expect( - stateVariables2["/_answer1"].stateValues - .creditAchieved, - ).eq(1); - }); - - cy.get("[data-test=previous]").click(); - - cy.get(mathinputEditiableFieldAnchor).should( - "have.text", - `${n}`, - ); - cy.get(mathinputCorrectAnchor).should("be.visible"); - - cy.get("[data-test=next]").click(); - - cy.get(textinputAnchor).should("have.value", l); - cy.get(textinputCorrectAnchor).should("be.visible"); - }); - }); - } - }); - - it("Shuffle and select orders, numVariants not specified", () => { - let doenetML = ` - - - - A - a - - - - - B - a - - - - C - a - - - - - - `; - - let selectionByVariant = {}; - - for (let ind = 5; ind <= 1500; ind += 250) { - if (ind > 5) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 5) { - cy.get("[data-test=previous]").click(); - } - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 1000) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).gte(1); - expect(activityData.variantsByPage[0]).lte(100); - expect(activityData.variantsByPage[1]).gte(1); - expect(activityData.variantsByPage[1]).lte(100); - - let selection = { - order: activityData.order, - variantsByPage: activityData.variantsByPage, - }; - - let titles = []; - - let stateVariables1 = await win.returnAllStateVariables1(); - let title1 = stateVariables1["/_title1"].stateValues.value; - - titles.push(title1); - - let page1 = { - title: title1, - n: stateVariables1["/n"].stateValues.value, - }; - - selection.page1 = page1; - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_title1")).should( - "not.have.text", - title1, - ); - cy.get(cesc("#page2\\/_text1")) - .should("have.text", "a") - .then(async () => { - let stateVariables2 = - await win.returnAllStateVariables2(); - let title2 = - stateVariables2["/_title1"].stateValues.value; - - titles.push(title2); - - let page2 = { - title: title2, - n: stateVariables2["/n"].stateValues.value, - }; - - titles.sort(); - - let validTitles = - (titles[0] === "A" && - (titles[1] === "B" || titles[1] === "C")) || - (titles[0] === "B" && titles[1] === "C"); - - expect(validTitles).eq(true); - - selection.page2 = page2; - - if ( - selectionByVariant[activityData.variantIndex] === - undefined - ) { - selectionByVariant[activityData.variantIndex] = - selection; - } else { - expect(selection).eqls( - selectionByVariant[activityData.variantIndex], - ); - } - }); - }); - } - }); - - it("Two pages, unique variants, variants to exclude", () => { - let doenetML = ` - - - a - - - - - b - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, unique variants, variants to include", () => { - let doenetML = ` - - - a - - - - - b - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, named variants, variants to exclude", () => { - let doenetML = ` - - - a - - - - - b - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, named variants, variants to include", () => { - let doenetML = ` - - - a - - - - - b - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, variants from problem, variants to exclude", () => { - let doenetML = ` - - - - a - - - - - - - b - - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, variants from problem, variants to include", () => { - let doenetML = ` - - - - a - - - - - - - b - - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, variants from document and problem, variants to exclude in problem", () => { - let doenetML = ` - - - - - a - - - - - - - - b - - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, variants from document and problem, variants to include in problem", () => { - let doenetML = ` - - - - - a - - - - - - - - b - - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, variants from document and problem, variant to exclude in document and problem", () => { - let doenetML = ` - - - - - a - - - - - - - - b - - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - let docVariantOptions1 = ["a", "c"]; - let docVariantOptions2 = ["a", "b", "d"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - expect( - stateVariables1["/_document1"].sharedParameters.variantName, - ).eq(docVariantOptions1[activityData.variantsByPage[0] - 1]); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - expect( - stateVariables2["/_document1"].sharedParameters - .variantName, - ).eq( - docVariantOptions2[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); - - it("Two pages, variants from document and problem, variant to include in document and problem", () => { - let doenetML = ` - - - - - a - - - - - - - - b - - - - - - `; - - for (let ind = 1; ind <= 20; ind += 5) { - if (ind > 1) { - cy.reload(); - } - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: ind, - }, - "*", - ); - }); - - if (ind > 1) { - cy.get("[data-test=previous]").click(); - } - - let nFromVariant = [2, 5]; - let lFromVariant = ["a", "e", "g"]; - let docVariantOptions1 = ["a", "c"]; - let docVariantOptions2 = ["a", "b", "d"]; - - cy.get(cesc("#page1\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let activityData = win.returnActivityData(); - - expect(activityData.requestedVariantIndex).eq(ind); - expect(activityData.variantIndex).eq(((ind - 1) % 6) + 1); - expect(activityData.variantsByPage.length).eq(2); - expect(activityData.variantsByPage[0]).eq( - ((activityData.variantIndex - 1) % 2) + 1, - ); - expect(activityData.variantsByPage[1]).eq( - ((activityData.variantIndex - 1) % 3) + 1, - ); - - let stateVariables1 = await win.returnAllStateVariables1(); - - expect(stateVariables1["/n"].stateValues.value).eq( - nFromVariant[activityData.variantsByPage[0] - 1], - ); - expect( - stateVariables1["/_document1"].sharedParameters.variantName, - ).eq(docVariantOptions1[activityData.variantsByPage[0] - 1]); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_text1")).should("have.text", "b"); - - cy.window().then(async (win) => { - let stateVariables2 = await win.returnAllStateVariables2(); - - expect(stateVariables2["/l"].stateValues.value).eq( - lFromVariant[activityData.variantsByPage[1] - 1], - ); - expect( - stateVariables2["/_document1"].sharedParameters - .variantName, - ).eq( - docVariantOptions2[activityData.variantsByPage[1] - 1], - ); - }); - }); - } - }); -}); diff --git a/packages/test-cypress/cypress/e2e/ActivityViewer/compiledActivity.cy.js b/packages/test-cypress/cypress/e2e/ActivityViewer/compiledActivity.cy.js deleted file mode 100644 index 639fb40cf..000000000 --- a/packages/test-cypress/cypress/e2e/ActivityViewer/compiledActivity.cy.js +++ /dev/null @@ -1,78 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("Compiled activity tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("Minimal activity definition", () => { - // Note: - // - missing xmlns attribute on activity document - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - hi - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_document1")).should("contain.text", "hi"); - }); - - it("Minimal activity definition, with xmlns", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - hi - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_document1")).should("contain.text", "hi"); - }); - - it("page definition sent to activity viewer", () => { - // Note: - // - missing xmlns attribute on page document - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - hi - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_document1")).should("contain.text", "hi"); - }); - - it("page definition sent to activity viewer, with xmlns", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - hi - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_document1")).should("contain.text", "hi"); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js b/packages/test-cypress/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js deleted file mode 100644 index d8023d82a..000000000 --- a/packages/test-cypress/cypress/e2e/ActivityViewer/relationshipsAmongPages.cy.js +++ /dev/null @@ -1,775 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("Relationships among pages tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("Problem numbering continues across pages", () => { - let doenetML = ` - - - -

The first problem

-
-
- - -

The second problem

-
-
- - -

The third problem

-
- -

The fourth problem

-
-
- - -

The fifth problem

-
- - Named problem -

The sixth problem

-
-
- - -

The seventh problem

-
-
-
- `; - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#page1\\/_problem1_title")).should( - "have.text", - "Problem 1", - ); - cy.get(cesc("#page1\\/_p1")).should("have.text", "The first problem"); - - cy.get(cesc("#page2\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page2\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_problem2_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p2")).should("not.exist"); - cy.get(cesc("#page4\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page4\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_problem2_title")).should("not.exist"); - cy.get(cesc("#page4\\/_title1")).should("not.exist"); - cy.get(cesc("#page4\\/_p2")).should("not.exist"); - cy.get(cesc("#page5\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page5\\/_p1")).should("not.exist"); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_problem1_title")).should( - "have.text", - "Problem 2", - ); - cy.get(cesc("#page2\\/_p1")).should("have.text", "The second problem"); - - cy.get(cesc("#page1\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page1\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_problem2_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p2")).should("not.exist"); - cy.get(cesc("#page4\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page4\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_problem2_title")).should("not.exist"); - cy.get(cesc("#page4\\/_title1")).should("not.exist"); - cy.get(cesc("#page4\\/_p2")).should("not.exist"); - cy.get(cesc("#page5\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page5\\/_p1")).should("not.exist"); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page3\\/_problem1_title")).should( - "have.text", - "Problem 3", - ); - cy.get(cesc("#page3\\/_p1")).should("have.text", "The third problem"); - cy.get(cesc("#page3\\/_problem2_title")).should( - "have.text", - "Problem 4", - ); - cy.get(cesc("#page3\\/_p2")).should("have.text", "The fourth problem"); - - cy.get(cesc("#page1\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page1\\/_p1")).should("not.exist"); - cy.get(cesc("#page2\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page2\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page4\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_problem2_title")).should("not.exist"); - cy.get(cesc("#page4\\/_title1")).should("not.exist"); - cy.get(cesc("#page4\\/_p2")).should("not.exist"); - cy.get(cesc("#page5\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page5\\/_p1")).should("not.exist"); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page4\\/_problem1_title")).should( - "have.text", - "Problem 5", - ); - cy.get(cesc("#page4\\/_p1")).should("have.text", "The fifth problem"); - cy.get(cesc("#page4\\/_problem2_title")).should( - "have.text", - "Problem 6: Named problem", - ); - cy.get(cesc("#page4\\/_title1")).should("have.text", "Named problem"); - cy.get(cesc("#page4\\/_p2")).should("have.text", "The sixth problem"); - - cy.get(cesc("#page1\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page1\\/_p1")).should("not.exist"); - cy.get(cesc("#page2\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page2\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_problem2_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p2")).should("not.exist"); - cy.get(cesc("#page5\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page5\\/_p1")).should("not.exist"); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page5\\/_problem1_title")).should( - "have.text", - "Problem 7", - ); - cy.get(cesc("#page5\\/_p1")).should("have.text", "The seventh problem"); - - cy.get(cesc("#page1\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page1\\/_p1")).should("not.exist"); - cy.get(cesc("#page2\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page2\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_problem2_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p2")).should("not.exist"); - cy.get(cesc("#page4\\/_problem1_title")).should("not.exist"); - cy.get(cesc("#page4\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_problem2_title")).should("not.exist"); - cy.get(cesc("#page4\\/_title1")).should("not.exist"); - cy.get(cesc("#page4\\/_p2")).should("not.exist"); - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_paginate").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - // Note: activity is sufficiently short that even page 5 - // is within the buffer to be activated without needing to scroll - - cy.get(cesc("#page1\\/_problem1_title")).should( - "have.text", - "Problem 1", - ); - cy.get(cesc("#page1\\/_p1")).should("have.text", "The first problem"); - - cy.get(cesc("#page2\\/_problem1_title")).should( - "have.text", - "Problem 2", - ); - cy.get(cesc("#page2\\/_p1")).should("have.text", "The second problem"); - - cy.get(cesc("#page3\\/_problem1_title")).should( - "have.text", - "Problem 3", - ); - cy.get(cesc("#page3\\/_p1")).should("have.text", "The third problem"); - cy.get(cesc("#page3\\/_problem2_title")).should( - "have.text", - "Problem 4", - ); - cy.get(cesc("#page3\\/_p2")).should("have.text", "The fourth problem"); - - cy.get(cesc("#page4\\/_problem1_title")).should( - "have.text", - "Problem 5", - ); - cy.get(cesc("#page4\\/_p1")).should("have.text", "The fifth problem"); - cy.get(cesc("#page4\\/_problem2_title")).should( - "have.text", - "Problem 6: Named problem", - ); - cy.get(cesc("#page4\\/_title1")).should("have.text", "Named problem"); - cy.get(cesc("#page4\\/_p2")).should("have.text", "The sixth problem"); - - cy.get(cesc("#page5\\/_problem1_title")).should( - "have.text", - "Problem 7", - ); - cy.get(cesc("#page5\\/_p1")).should("have.text", "The seventh problem"); - }); - - it("Section numbering continues across pages", () => { - let doenetML = ` - - -
-

The first section

-
-
- -
-

The second section

- -

First subsection of second section

-
- -

Second subsection of second section

-
-
-
- -
-

The third section

-
-
-

The fourth section

- -

First subsection of fourth section

-
- -

Second subsection of fourth section

-
-
-
- -
-

The fifth section

-
-
- Named section -

The sixth section

- -

First subsection of sixth section

-
- -

Second subsection of sixth section

-
-
-
- -
-

The seventh section

-
-
-
- `; - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#page1\\/_section1_title")).should( - "have.text", - "Section 1", - ); - cy.get(cesc("#page1\\/_p1")).should("have.text", "The first section"); - - cy.get(cesc("#page2\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page2\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_section2_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p2")).should("not.exist"); - cy.get(cesc("#page4\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page4\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_section2_title")).should("not.exist"); - cy.get(cesc("#page4\\/_title1")).should("not.exist"); - cy.get(cesc("#page4\\/_p2")).should("not.exist"); - cy.get(cesc("#page5\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page5\\/_p1")).should("not.exist"); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/_section1_title")).should( - "have.text", - "Section 2", - ); - cy.get(cesc("#page2\\/_p1")).should("have.text", "The second section"); - - cy.get(cesc("#page1\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page1\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_section2_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p2")).should("not.exist"); - cy.get(cesc("#page4\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page4\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_section2_title")).should("not.exist"); - cy.get(cesc("#page4\\/_title1")).should("not.exist"); - cy.get(cesc("#page4\\/_p2")).should("not.exist"); - cy.get(cesc("#page5\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page5\\/_p1")).should("not.exist"); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page3\\/_section1_title")).should( - "have.text", - "Section 3", - ); - cy.get(cesc("#page3\\/_p1")).should("have.text", "The third section"); - cy.get(cesc("#page3\\/_section2_title")).should( - "have.text", - "Section 4", - ); - cy.get(cesc("#page3\\/_p2")).should("have.text", "The fourth section"); - - cy.get(cesc("#page1\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page1\\/_p1")).should("not.exist"); - cy.get(cesc("#page2\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page2\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page4\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_section2_title")).should("not.exist"); - cy.get(cesc("#page4\\/_title1")).should("not.exist"); - cy.get(cesc("#page4\\/_p2")).should("not.exist"); - cy.get(cesc("#page5\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page5\\/_p1")).should("not.exist"); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page4\\/_section1_title")).should( - "have.text", - "Section 5", - ); - cy.get(cesc("#page4\\/_p1")).should("have.text", "The fifth section"); - cy.get(cesc("#page4\\/_section2_title")).should( - "have.text", - "Section 6: Named section", - ); - cy.get(cesc("#page4\\/_title1")).should("have.text", "Named section"); - cy.get(cesc("#page4\\/_p2")).should("have.text", "The sixth section"); - - cy.get(cesc("#page1\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page1\\/_p1")).should("not.exist"); - cy.get(cesc("#page2\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page2\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_section2_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p2")).should("not.exist"); - cy.get(cesc("#page5\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page5\\/_p1")).should("not.exist"); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page5\\/_section1_title")).should( - "have.text", - "Section 7", - ); - cy.get(cesc("#page5\\/_p1")).should("have.text", "The seventh section"); - - cy.get(cesc("#page1\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page1\\/_p1")).should("not.exist"); - cy.get(cesc("#page2\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page2\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p1")).should("not.exist"); - cy.get(cesc("#page3\\/_section2_title")).should("not.exist"); - cy.get(cesc("#page3\\/_p2")).should("not.exist"); - cy.get(cesc("#page4\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page4\\/_p1")).should("not.exist"); - cy.get(cesc("#page4\\/_section2_title")).should("not.exist"); - cy.get(cesc("#page4\\/_title1")).should("not.exist"); - cy.get(cesc("#page4\\/_p2")).should("not.exist"); - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_paginate").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#page1\\/_section1_title")).should( - "have.text", - "Section 1", - ); - cy.get(cesc("#page1\\/_p1")).should("have.text", "The first section"); - - cy.get("#page2").scrollIntoView(); - cy.get(cesc("#page2\\/_section1_title")).should( - "have.text", - "Section 2", - ); - cy.get(cesc("#page2\\/_p1")).should("have.text", "The second section"); - - cy.get("#page3").scrollIntoView(); - cy.get(cesc("#page3\\/_section1_title")).should( - "have.text", - "Section 3", - ); - cy.get(cesc("#page3\\/_p1")).should("have.text", "The third section"); - cy.get(cesc("#page3\\/_section2_title")).should( - "have.text", - "Section 4", - ); - cy.get(cesc("#page3\\/_p2")).should("have.text", "The fourth section"); - - cy.get("#page4").scrollIntoView(); - cy.get(cesc("#page4\\/_section1_title")).should( - "have.text", - "Section 5", - ); - cy.get(cesc("#page4\\/_p1")).should("have.text", "The fifth section"); - cy.get(cesc("#page4\\/_section2_title")).should( - "have.text", - "Section 6: Named section", - ); - cy.get(cesc("#page4\\/_title1")).should("have.text", "Named section"); - cy.get(cesc("#page4\\/_p2")).should("have.text", "The sixth section"); - - cy.get("#page5").scrollIntoView(); - cy.get(cesc("#page5\\/_section1_title")).should( - "have.text", - "Section 7", - ); - cy.get(cesc("#page5\\/_p1")).should("have.text", "The seventh section"); - }); - - it("Links across pages", () => { - let doenetML = ` - - -
-

Link to paragraph above aside

-

Link to aside

-

Link to page 2

-

Link to paragraph above page 2 aside

-

Link to page 2 aside

-

Checkbox to make it save state:

- - -

Paragraph above aside

- - - - -
-
- -
-

Link to paragraph above aside

-

Link to aside

-

Link to page 1

-

Link to paragraph above page 1 aside

-

Link to page 1 aside

-

Checkbox to make it save state:

- - - -

Paragraph above aside

- - - - -
-
-
- `; - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_allowLocalState").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#page1\\/_section1_title")).should( - "have.text", - "Section 1", - ); - cy.get(cesc("#page2\\/_section1_title")).should("not.exist"); - cy.url().should("match", /#page1$/); - - cy.window().then(async (win) => { - expect(win.scrollY).eq(0); - }); - - cy.get(cesc("#page1\\/bi")).click(); - cy.get(cesc("#page1\\/b")).should("have.text", "true"); - - cy.get(cesc("#page1\\/toAbove")).click(); - cy.url().should("match", /#page1\\\/pAbove$/); - - cy.get(cesc("#page1\\/pAbove")).then((el) => { - let rect = el[0].getBoundingClientRect(); - expect(rect.top).gt(-1).lt(1); - }); - - cy.get(cesc("#page1\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page1\\/insideAside")).should("not.exist"); - - cy.get(cesc("#page1\\/toPage2")).click(); - - cy.get(cesc("#page2\\/_section1_title")).should( - "have.text", - "Section 2", - ); - cy.get(cesc("#page1\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page2\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page2\\/insideAside")).should("not.exist"); - - cy.window().then(async (win) => { - expect(win.scrollY).lt(100); - }); - - cy.get(cesc("#page2\\/bi")).click(); - cy.get(cesc("#page2\\/b")).should("have.text", "true"); - - cy.get(cesc("#page2\\/toAside1")).click(); - - cy.get(cesc("#page1\\/_section1_title")).should( - "have.text", - "Section 1", - ); - cy.get(cesc("#page2\\/_section1_title")).should("not.exist"); - - cy.url().should("match", /#page1\\\/aside$/); - - cy.get(cesc("#page1\\/aside")).then((el) => { - let rect = el[0].getBoundingClientRect(); - expect(rect.top).gt(-1).lt(1); - }); - - cy.get(cesc("#page1\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page1\\/insideAside")).should( - "have.text", - "Content in aside", - ); - - cy.get(cesc("#page1\\/toAbove2")).click(); - - cy.get(cesc("#page2\\/_section1_title")).should( - "have.text", - "Section 2", - ); - cy.get(cesc("#page1\\/_section1_title")).should("not.exist"); - cy.get(cesc("#page2\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page2\\/insideAside")).should("not.exist"); - - cy.url().should("match", /#page2\\\/pAbove$/); - - cy.get(cesc("#page2\\/pAbove")).then((el) => { - let rect = el[0].getBoundingClientRect(); - expect(rect.top).gt(-1).lt(1); - }); - - cy.get("[data-test=previous]").click(); - - cy.url().should("match", /#page1$/); - - cy.get(cesc("#page1\\/bi")).click(); - cy.get(cesc("#page1\\/b")).should("have.text", "false"); - - cy.wait(2000); // to wait for debounce - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#page1\\/b")).should("have.text", "false"); - - cy.get(cesc("#page1\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page1\\/insideAside")).should( - "have.text", - "Content in aside", - ); - - cy.url().should("match", /#page1$/); - - cy.get("[data-test=next]").click(); - - cy.get(cesc("#page2\\/b")).should("have.text", "true"); - cy.get(cesc("#page2\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page2\\/insideAside")).should("not.exist"); - cy.url().should("match", /#page2$/); - - cy.get("[data-test=previous]").click(); - - cy.get(cesc("#page1\\/b")).should("have.text", "false"); - cy.url().should("match", /#page1$/); - - cy.get(cesc("#page1\\/asideTitle")).click(); - - cy.get(cesc("#page1\\/insideAside")).should("not.exist"); - - cy.get(cesc("#page1\\/toAside2")).click(); - - cy.get(cesc("#page2\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page2\\/insideAside")).should( - "have.text", - "Content in aside", - ); - - cy.url().should("match", /#page2\\\/aside$/); - - cy.get(cesc("#page2\\/aside")).then((el) => { - let rect = el[0].getBoundingClientRect(); - expect(rect.top).gt(-1).lt(1); - }); - - cy.wait(2000); // to wait for debounce - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#page2\\/b")).should("have.text", "true"); - cy.get(cesc("#page2\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page2\\/insideAside")).should( - "have.text", - "Content in aside", - ); - - cy.url().should("match", /#page2\\\/aside$/); - - cy.get(cesc("#page2\\/aside")).then((el) => { - let rect = el[0].getBoundingClientRect(); - expect(rect.top).gt(-1).lt(1); - }); - - cy.get(cesc("#page2\\/toAbove1")).click(); - - cy.get(cesc("#page1\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page1\\/insideAside")).should("not.exist"); - - cy.url().should("match", /#page1\\\/pAbove$/); - - cy.get(cesc("#page1\\/pAbove")).then((el) => { - let rect = el[0].getBoundingClientRect(); - expect(rect.top).gt(-1).lt(1); - }); - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_paginate").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc("#page1\\/b")).should("have.text", "false"); - cy.get(cesc("#page1\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page1\\/insideAside")).should("not.exist"); - - cy.url().should("match", /#page1\\\/pAbove$/); - - cy.get(cesc("#page1\\/pAbove")).then((el) => { - let rect = el[0].getBoundingClientRect(); - expect(rect.top).gt(-1).lt(1); - }); - - cy.get(cesc("#page2\\/b")).should("have.text", "true"); - cy.get(cesc("#page2\\/asideTitle")).should("have.text", "The aside"); - cy.get(cesc("#page2\\/insideAside")).should( - "have.text", - "Content in aside", - ); - - cy.get(cesc("#page1\\/toAbove2")).click(); - - cy.url().should("match", /#page2\\\/pAbove$/); - - cy.waitUntil(() => - cy.get(cesc("#page2\\/pAbove")).then((el) => { - let rect = el[0].getBoundingClientRect(); - return rect.top > -1 && rect.top < 1; - }), - ); - - cy.get(cesc("#page2\\/toAside1")).click(); - - cy.url().should("match", /#page1\\\/aside$/); - - cy.waitUntil(() => - cy.get(cesc("#page1\\/aside")).then((el) => { - let rect = el[0].getBoundingClientRect(); - return rect.top > -1 && rect.top < 1; - }), - ); - - cy.get(cesc("#page1\\/insideAside")).should( - "have.text", - "Content in aside", - ); - - cy.get(cesc("#page2\\/aside")).scrollIntoView(); - cy.url().should("match", /#page2$/); - - cy.get(cesc("#page1\\/aside")).scrollIntoView(); - cy.url().should("match", /#page1$/); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/PageViewer/pageViewerAttributes.cy.js b/packages/test-cypress/cypress/e2e/PageViewer/pageViewerAttributes.cy.js new file mode 100644 index 000000000..b6b8773bc --- /dev/null +++ b/packages/test-cypress/cypress/e2e/PageViewer/pageViewerAttributes.cy.js @@ -0,0 +1,62 @@ +import { cesc2, deepCompare } from "@doenet/utils"; + +describe("PageViewer Attribute Tests", function () { + beforeEach(() => { + cy.clearIndexedDB(); + cy.visit("/"); + }); + + it("get variants without rendering or starting core", () => { + let allPossibleVariants = null; + + function variantsListener(e) { + if (e.data.subject === "SPLICE.allPossibleVariants") { + allPossibleVariants = e.data.args.allPossibleVariants; + } + } + + cy.window().then(async (win) => { + win.addEventListener("message", variantsListener); + }); + + cy.get("#testRunner_toggleControls").click(); + cy.get("#testRunner_render").click(); + cy.wait(100); + cy.get("#testRunner_toggleControls").click(); + + cy.window().then(async (win) => { + win.postMessage( + { + doenetML: ` + Hello + + `, + }, + "*", + ); + }); + + cy.waitUntil(() => { + if (!allPossibleVariants) { + return false; + } + return deepCompare( + [...allPossibleVariants], + ["a", "b", "c", "d", "e", "f", "g"], + ); + }); + + cy.window().then(async (win) => { + win.removeEventListener("message", variantsListener); + }); + + cy.get(cesc2("#/t")).should("not.exist"); + + cy.log("Core has not been initialized"); + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + + expect(stateVariables).eqls({}); + }); + }); +}); diff --git a/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js b/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js index 71e057352..75cbeecec 100644 --- a/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js +++ b/packages/test-cypress/cypress/e2e/dynamicalsystem/cobwebpolyline.cy.js @@ -66,17 +66,10 @@ describe("CobwebPolyline Tag Tests", function () { .eq(0) .click(); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + "x0=1\n", + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/addLine_button")).click(); cy.get(cesc2("#/gradedApplet/correctCobwebbing_submit")).should( @@ -119,26 +112,10 @@ describe("CobwebPolyline Tag Tests", function () { "be.visible", ); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x1=${Math.round(x1 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(2) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + `x0=1x1=${Math.round(x1 * 10000) / 10000}\n`, + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/deleteLine_button")).click(); cy.get(cesc2("#/gradedApplet/correctCobwebbing_submit")).click(); @@ -150,17 +127,10 @@ describe("CobwebPolyline Tag Tests", function () { ); cy.get(cesc2("#/gradedApplet/startFeedback")).should("be.visible"); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + "x0=1\n", + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/addLine_button")).click(); cy.get(cesc2("#/gradedApplet/correctCobwebbing_submit")).click(); @@ -176,26 +146,10 @@ describe("CobwebPolyline Tag Tests", function () { "be.visible", ); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x1=${Math.round(x1 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(2) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + `x0=1x1=${Math.round(x1 * 10000) / 10000}\n`, + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/addLine_button")).click(); cy.get(cesc2("#/gradedApplet/correctCobwebbing_submit")).click(); @@ -225,26 +179,10 @@ describe("CobwebPolyline Tag Tests", function () { "be.visible", ); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x1=${Math.round(x1 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(2) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + `x0=1x1=${Math.round(x1 * 10000) / 10000}\n`, + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/addLine_button")).click(); cy.get(cesc2("#/gradedApplet/correctCobwebbing_submit")).click(); @@ -266,35 +204,10 @@ describe("CobwebPolyline Tag Tests", function () { "be.visible", ); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x1=${Math.round(x1 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x2=${Math.round(x2 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(3) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + `x0=1x1=${Math.round(x1 * 10000) / 10000}x2=${Math.round(x2 * 10000) / 10000}\n`, + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/addLine_button")).click(); @@ -317,35 +230,10 @@ describe("CobwebPolyline Tag Tests", function () { "be.visible", ); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x1=${Math.round(x1 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x2=${Math.round(x2 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(3) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + `x0=1x1=${Math.round(x1 * 10000) / 10000}x2=${Math.round(x2 * 10000) / 10000}\n`, + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/addLine_button")).click(); cy.get(cesc2("#/gradedApplet/correctCobwebbing_submit")).click(); @@ -369,44 +257,10 @@ describe("CobwebPolyline Tag Tests", function () { "be.visible", ); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x1=${Math.round(x1 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x2=${Math.round(x2 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(3) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x3=${Math.round(x3 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(4) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + `x0=1x1=${Math.round(x1 * 10000) / 10000}x2=${Math.round(x2 * 10000) / 10000}x3=${Math.round(x3 * 10000) / 10000}\n`, + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/addLine_button")).click(); cy.get(cesc2("#/gradedApplet/correctCobwebbing_submit")).click(); @@ -434,44 +288,10 @@ describe("CobwebPolyline Tag Tests", function () { "be.visible", ); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x1=${Math.round(x1 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x2=${Math.round(x2 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(3) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x3=${Math.round(x3 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(4) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + `x0=1x1=${Math.round(x1 * 10000) / 10000}x2=${Math.round(x2 * 10000) / 10000}x3=${Math.round(x3 * 10000) / 10000}\n`, + ); cy.get(cesc2("#/gradedApplet/cobwebApplet/addLine_button")).click(); cy.get(cesc2("#/gradedApplet/correctCobwebbing_submit")).click(); @@ -500,53 +320,10 @@ describe("CobwebPolyline Tag Tests", function () { "be.visible", ); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x0=1"); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(1) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x1=${Math.round(x1 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(2) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x2=${Math.round(x2 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(3) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x3=${Math.round(x3 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(4) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal( - `x4=${Math.round(x4 * 10000) / 10000}`, - ); - }); - cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")) - .find(".mjx-mtr") - .eq(5) - .should("not.exist"); + cy.get(cesc2("#/gradedApplet/cobwebApplet/calculatedValue")).should( + "contain.text", + `x0=1x1=${Math.round(x1 * 10000) / 10000}x2=${Math.round(x2 * 10000) / 10000}x3=${Math.round(x3 * 10000) / 10000}x4=${Math.round(x4 * 10000) / 10000}\n`, + ); }); it("cobweb intro tutorial", () => { diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/animatefromsequence.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/animatefromsequence.cy.js index 1be13ee4c..fb7ad6a2b 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/animatefromsequence.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/animatefromsequence.cy.js @@ -2306,17 +2306,17 @@ describe("AnimateFromSequence Tag Tests", function () { a -

1 2 3

+

(1, 2, 3)

Component to animate:

- + -

$nl{name="nl2"}

+

$A{name="A2"}

-

$nl.number3{assignNames="n3"}

+

$A.x3{assignNames="x3"}

`, }, @@ -2326,27 +2326,27 @@ describe("AnimateFromSequence Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.get(cesc("#\\/p1")).should("have.text", "1, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "1, 2, 3"); + cy.get(cesc("#\\/p1")).should("have.text", "(1,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(1,2,3)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); expect(stateVariables["/x"].stateValues.value).eq(1); - expect(stateVariables["/nl"].stateValues.numbers).eqls([1, 2, 3]); - expect(stateVariables["/nl2"].stateValues.numbers).eqls([1, 2, 3]); + expect(stateVariables["/A"].stateValues.xs).eqls([1, 2, 3]); + expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2, 3]); expect(stateVariables["/x"].stateValues.selectedIndex).eq(1); expect(stateVariables["/x"].stateValues.animationOn).eq(false); }); cy.get(cesc(`#\\/b`)).click(); - cy.get(cesc("#\\/p1")).should("have.text", "2, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "2, 2, 3"); - cy.get(cesc("#\\/p1")).should("have.text", "3, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "3, 2, 3"); - cy.get(cesc("#\\/p1")).should("have.text", "4, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "4, 2, 3"); - cy.get(cesc("#\\/p1")).should("have.text", "5, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "5, 2, 3"); + cy.get(cesc("#\\/p1")).should("have.text", "(2,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(2,2,3)"); + cy.get(cesc("#\\/p1")).should("have.text", "(3,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(3,2,3)"); + cy.get(cesc("#\\/p1")).should("have.text", "(4,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(4,2,3)"); + cy.get(cesc("#\\/p1")).should("have.text", "(5,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(5,2,3)"); cy.get(cesc(`#\\/b`)).click(); @@ -2364,12 +2364,12 @@ describe("AnimateFromSequence Tag Tests", function () { lastValue1 = stateVariables["/x"].stateValues.value; expect(lastValue1 === 5 || lastValue1 === 6).be.true; - expect(stateVariables["/nl"].stateValues.numbers).eqls([ + expect(stateVariables["/A"].stateValues.xs).eqls([ lastValue1, 2, 3, ]); - expect(stateVariables["/nl2"].stateValues.numbers).eqls([ + expect(stateVariables["/A2"].stateValues.xs).eqls([ lastValue1, 2, 3, @@ -2379,8 +2379,8 @@ describe("AnimateFromSequence Tag Tests", function () { ); expect(stateVariables["/x"].stateValues.animationOn).eq(false); - cy.get(cesc("#\\/p1")).should("have.text", `${lastValue1}, 2, 3`); - cy.get(cesc("#\\/p2")).should("have.text", `${lastValue1}, 2, 3`); + cy.get(cesc("#\\/p1")).should("have.text", `(${lastValue1},2,3)`); + cy.get(cesc("#\\/p2")).should("have.text", `(${lastValue1},2,3)`); }); cy.log("Animate index 2"); @@ -2394,43 +2394,43 @@ describe("AnimateFromSequence Tag Tests", function () { .then(() => { cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 3, 3`, + `(${lastValue1},3,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 3, 3`, + `(${lastValue1},3,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 4, 3`, + `(${lastValue1},4,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 4, 3`, + `(${lastValue1},4,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 5, 3`, + `(${lastValue1},5,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 5, 3`, + `(${lastValue1},5,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 6, 3`, + `(${lastValue1},6,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 6, 3`, + `(${lastValue1},6,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 7, 3`, + `(${lastValue1},7,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 7, 3`, + `(${lastValue1},7,3)`, ); }); @@ -2450,12 +2450,12 @@ describe("AnimateFromSequence Tag Tests", function () { lastValue2 = stateVariables["/x"].stateValues.value; expect(lastValue2 === 7 || lastValue2 === 8).be.true; - expect(stateVariables["/nl"].stateValues.numbers).eqls([ + expect(stateVariables["/A"].stateValues.xs).eqls([ lastValue1, lastValue2, 3, ]); - expect(stateVariables["/nl2"].stateValues.numbers).eqls([ + expect(stateVariables["/A2"].stateValues.xs).eqls([ lastValue1, lastValue2, 3, @@ -2467,11 +2467,11 @@ describe("AnimateFromSequence Tag Tests", function () { cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, ${lastValue2}, 3`, + `(${lastValue1},${lastValue2},3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, ${lastValue2}, 3`, + `(${lastValue1},${lastValue2},3)`, ); }); @@ -2482,27 +2482,27 @@ describe("AnimateFromSequence Tag Tests", function () { .then(() => { cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 9, 3`, + `(${lastValue1},9,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 9, 3`, + `(${lastValue1},9,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 10, 3`, + `(${lastValue1},10,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 10, 3`, + `(${lastValue1},10,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 1, 3`, + `(${lastValue1},1,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 1, 3`, + `(${lastValue1},1,3)`, ); }); @@ -2510,10 +2510,10 @@ describe("AnimateFromSequence Tag Tests", function () { force: true, }); - cy.get(cesc("#\\/n3")).should("have.text", "4"); - cy.get(cesc("#\\/n3")).should("have.text", "5"); - cy.get(cesc("#\\/n3")).should("have.text", "6"); - cy.get(cesc("#\\/n3")).should("have.text", "7"); + cy.get(cesc("#\\/x3")).should("have.text", "4"); + cy.get(cesc("#\\/x3")).should("have.text", "5"); + cy.get(cesc("#\\/x3")).should("have.text", "6"); + cy.get(cesc("#\\/x3")).should("have.text", "7"); cy.get(cesc(`#\\/b`)).click(); @@ -2530,15 +2530,15 @@ describe("AnimateFromSequence Tag Tests", function () { let stateVariables = await win.returnAllStateVariables1(); lastValue3 = stateVariables["/x"].stateValues.value; expect(lastValue3 === 7 || lastValue3 === 8).be.true; - lastValue2 = stateVariables["/nl"].stateValues.numbers[1]; + lastValue2 = stateVariables["/A"].stateValues.xs[1]; expect(lastValue2 === 1 || lastValue2 === 2).be.true; - expect(stateVariables["/nl"].stateValues.numbers).eqls([ + expect(stateVariables["/A"].stateValues.xs).eqls([ lastValue1, lastValue2, lastValue3, ]); - expect(stateVariables["/nl2"].stateValues.numbers).eqls([ + expect(stateVariables["/A2"].stateValues.xs).eqls([ lastValue1, lastValue2, lastValue3, @@ -2551,11 +2551,11 @@ describe("AnimateFromSequence Tag Tests", function () { cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, ${lastValue2}, ${lastValue3}`, + `(${lastValue1},${lastValue2},${lastValue3})`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, ${lastValue2}, ${lastValue3}`, + `(${lastValue1},${lastValue2},${lastValue3})`, ); }); }); @@ -2568,17 +2568,17 @@ describe("AnimateFromSequence Tag Tests", function () { a -

1 2 3

+

(1, 2, 3)

Component to animate:

- + -

$nl{name="nl2"}

+

$A{name="A2"}

-

$nl.number3{assignNames="n3"}

+

$A.x3{assignNames="x3"}

`, }, @@ -2588,27 +2588,27 @@ describe("AnimateFromSequence Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.get(cesc("#\\/p1")).should("have.text", "1, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "1, 2, 3"); + cy.get(cesc("#\\/p1")).should("have.text", "(1,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(1,2,3)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); expect(stateVariables["/x"].stateValues.value).eq(1); - expect(stateVariables["/nl"].stateValues.numbers).eqls([1, 2, 3]); - expect(stateVariables["/nl2"].stateValues.numbers).eqls([1, 2, 3]); + expect(stateVariables["/A"].stateValues.xs).eqls([1, 2, 3]); + expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2, 3]); expect(stateVariables["/x"].stateValues.selectedIndex).eq(1); expect(stateVariables["/x"].stateValues.animationOn).eq(false); }); cy.get(cesc(`#\\/b`)).click(); - cy.get(cesc("#\\/p1")).should("have.text", "2, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "2, 2, 3"); - cy.get(cesc("#\\/p1")).should("have.text", "3, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "3, 2, 3"); - cy.get(cesc("#\\/p1")).should("have.text", "4, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "4, 2, 3"); - cy.get(cesc("#\\/p1")).should("have.text", "5, 2, 3"); - cy.get(cesc("#\\/p2")).should("have.text", "5, 2, 3"); + cy.get(cesc("#\\/p1")).should("have.text", "(2,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(2,2,3)"); + cy.get(cesc("#\\/p1")).should("have.text", "(3,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(3,2,3)"); + cy.get(cesc("#\\/p1")).should("have.text", "(4,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(4,2,3)"); + cy.get(cesc("#\\/p1")).should("have.text", "(5,2,3)"); + cy.get(cesc("#\\/p2")).should("have.text", "(5,2,3)"); cy.get(cesc(`#\\/b`)).click(); @@ -2626,12 +2626,12 @@ describe("AnimateFromSequence Tag Tests", function () { lastValue1 = stateVariables["/x"].stateValues.value; expect(lastValue1 === 5 || lastValue1 === 6).be.true; - expect(stateVariables["/nl"].stateValues.numbers).eqls([ + expect(stateVariables["/A"].stateValues.xs).eqls([ lastValue1, 2, 3, ]); - expect(stateVariables["/nl2"].stateValues.numbers).eqls([ + expect(stateVariables["/A2"].stateValues.xs).eqls([ lastValue1, 2, 3, @@ -2641,8 +2641,8 @@ describe("AnimateFromSequence Tag Tests", function () { ); expect(stateVariables["/x"].stateValues.animationOn).eq(false); - cy.get(cesc("#\\/p1")).should("have.text", `${lastValue1}, 2, 3`); - cy.get(cesc("#\\/p2")).should("have.text", `${lastValue1}, 2, 3`); + cy.get(cesc("#\\/p1")).should("have.text", `(${lastValue1},2,3)`); + cy.get(cesc("#\\/p2")).should("have.text", `(${lastValue1},2,3)`); }); cy.log("Animate index 2"); @@ -2656,43 +2656,43 @@ describe("AnimateFromSequence Tag Tests", function () { .then(() => { cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 3, 3`, + `(${lastValue1},3,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 3, 3`, + `(${lastValue1},3,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 4, 3`, + `(${lastValue1},4,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 4, 3`, + `(${lastValue1},4,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 5, 3`, + `(${lastValue1},5,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 5, 3`, + `(${lastValue1},5,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 6, 3`, + `(${lastValue1},6,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 6, 3`, + `(${lastValue1},6,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 7, 3`, + `(${lastValue1},7,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 7, 3`, + `(${lastValue1},7,3)`, ); }); @@ -2712,12 +2712,12 @@ describe("AnimateFromSequence Tag Tests", function () { lastValue2 = stateVariables["/x"].stateValues.value; expect(lastValue2 === 7 || lastValue2 === 8).be.true; - expect(stateVariables["/nl"].stateValues.numbers).eqls([ + expect(stateVariables["/A"].stateValues.xs).eqls([ lastValue1, lastValue2, 3, ]); - expect(stateVariables["/nl2"].stateValues.numbers).eqls([ + expect(stateVariables["/A2"].stateValues.xs).eqls([ lastValue1, lastValue2, 3, @@ -2729,11 +2729,11 @@ describe("AnimateFromSequence Tag Tests", function () { cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, ${lastValue2}, 3`, + `(${lastValue1},${lastValue2},3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, ${lastValue2}, 3`, + `(${lastValue1},${lastValue2},3)`, ); }); @@ -2744,27 +2744,27 @@ describe("AnimateFromSequence Tag Tests", function () { .then(() => { cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 9, 3`, + `(${lastValue1},9,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 9, 3`, + `(${lastValue1},9,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 10, 3`, + `(${lastValue1},10,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 10, 3`, + `(${lastValue1},10,3)`, ); cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, 1, 3`, + `(${lastValue1},1,3)`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, 1, 3`, + `(${lastValue1},1,3)`, ); }); @@ -2772,10 +2772,10 @@ describe("AnimateFromSequence Tag Tests", function () { force: true, }); - cy.get(cesc("#\\/n3")).should("have.text", "4"); - cy.get(cesc("#\\/n3")).should("have.text", "5"); - cy.get(cesc("#\\/n3")).should("have.text", "6"); - cy.get(cesc("#\\/n3")).should("have.text", "7"); + cy.get(cesc("#\\/x3")).should("have.text", "4"); + cy.get(cesc("#\\/x3")).should("have.text", "5"); + cy.get(cesc("#\\/x3")).should("have.text", "6"); + cy.get(cesc("#\\/x3")).should("have.text", "7"); cy.get(cesc(`#\\/b`)).click(); @@ -2792,15 +2792,15 @@ describe("AnimateFromSequence Tag Tests", function () { let stateVariables = await win.returnAllStateVariables1(); lastValue3 = stateVariables["/x"].stateValues.value; expect(lastValue3 === 7 || lastValue3 === 8).be.true; - lastValue2 = stateVariables["/nl"].stateValues.numbers[1]; + lastValue2 = stateVariables["/A"].stateValues.xs[1]; expect(lastValue2 === 1 || lastValue2 === 2).be.true; - expect(stateVariables["/nl"].stateValues.numbers).eqls([ + expect(stateVariables["/A"].stateValues.xs).eqls([ lastValue1, lastValue2, lastValue3, ]); - expect(stateVariables["/nl2"].stateValues.numbers).eqls([ + expect(stateVariables["/A2"].stateValues.xs).eqls([ lastValue1, lastValue2, lastValue3, @@ -2813,11 +2813,11 @@ describe("AnimateFromSequence Tag Tests", function () { cy.get(cesc("#\\/p1")).should( "have.text", - `${lastValue1}, ${lastValue2}, ${lastValue3}`, + `(${lastValue1},${lastValue2},${lastValue3})`, ); cy.get(cesc("#\\/p2")).should( "have.text", - `${lastValue1}, ${lastValue2}, ${lastValue3}`, + `(${lastValue1},${lastValue2},${lastValue3})`, ); }); }); @@ -2843,7 +2843,7 @@ describe("AnimateFromSequence Tag Tests", function () {

$nl{name="nl2"}

-

$nl.number3{assignNames="n3"}

+

$nl[3]{name="n3"}

`, }, @@ -3201,13 +3201,13 @@ describe("AnimateFromSequence Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - cy.get(cesc("#\\/a") + " .mjx-mrow").should("have.text", "1"); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("have.text", "1"); + cy.get(cesc("#\\/a")).should("have.text", "1"); + cy.get(cesc("#\\/a2")).should("have.text", "1"); cy.get(cesc(`#\\/b`)).click(); - cy.get(cesc("#\\/a") + " .mjx-mrow").should("have.text", "2"); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("have.text", "2"); - cy.get(cesc("#\\/a") + " .mjx-mrow").should("have.text", "3"); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("have.text", "3"); + cy.get(cesc("#\\/a")).should("have.text", "2"); + cy.get(cesc("#\\/a2")).should("have.text", "2"); + cy.get(cesc("#\\/a")).should("have.text", "3"); + cy.get(cesc("#\\/a2")).should("have.text", "3"); }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/answer.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/answer.cy.js index ac33fcbc3..fa8a2fd53 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/answer.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/answer.cy.js @@ -1462,20 +1462,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("not.exist"); cy.get(incorrectAnchor).should("not.exist"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); + cy.get(cesc(`#\\/cr`)).should("contain.text", "_"); + cy.get(cesc(`#\\/sr`)).should("contain.text", "_"); cy.get(cesc(`#\\/ca`)).should("have.text", "0"); cy.get(cesc("#\\/val") + " textarea").type("3{enter}", { force: true }); @@ -1484,22 +1472,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("not.exist"); cy.get(incorrectAnchor).should("not.exist"); - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("contain.text", "3"); - - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); + cy.get(cesc(`#\\/cr`)).should("have.text", "3"); + cy.get(cesc(`#\\/sr`)).should("contain.text", "_"); cy.get(cesc(`#\\/ca`)).should("have.text", "0"); cy.get(cesc("#\\/a_submit")).click(); @@ -1508,20 +1482,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("not.exist"); cy.get(incorrectAnchor).should("be.visible"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); + cy.get(cesc(`#\\/cr`)).should("have.text", "3"); + cy.get(cesc(`#\\/sr`)).should("have.text", "3"); cy.get(cesc(`#\\/ca`)).should("have.text", "0"); cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}4", { @@ -1532,20 +1494,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("not.exist"); cy.get(incorrectAnchor).should("not.exist"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); + cy.get(cesc(`#\\/cr`)).should("have.text", "3"); + cy.get(cesc(`#\\/sr`)).should("have.text", "3"); cy.get(cesc(`#\\/ca`)).should("have.text", "0"); cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}3", { @@ -1556,20 +1506,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("not.exist"); cy.get(incorrectAnchor).should("not.exist"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); + cy.get(cesc(`#\\/cr`)).should("have.text", "3"); + cy.get(cesc(`#\\/sr`)).should("have.text", "3"); cy.get(cesc(`#\\/ca`)).should("have.text", "0"); cy.get(cesc("#\\/a_submit")).click(); @@ -1577,20 +1515,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("not.exist"); cy.get(incorrectAnchor).should("be.visible"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); + cy.get(cesc(`#\\/cr`)).should("have.text", "3"); + cy.get(cesc(`#\\/sr`)).should("have.text", "3"); cy.get(cesc(`#\\/ca`)).should("have.text", "0"); cy.get(cesc("#\\/val") + " textarea").type("{end}{backspace}5", { @@ -1601,20 +1527,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("not.exist"); cy.get(incorrectAnchor).should("not.exist"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); + cy.get(cesc(`#\\/cr`)).should("have.text", "3"); + cy.get(cesc(`#\\/sr`)).should("have.text", "3"); cy.get(cesc(`#\\/ca`)).should("have.text", "0"); cy.get(cesc("#\\/val") + " textarea").blur(); @@ -1623,21 +1537,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("not.exist"); cy.get(incorrectAnchor).should("not.exist"); - cy.get(cesc(`#\\/cr`) + ` .mjx-mrow`).should("have.text", "5"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); + cy.get(cesc(`#\\/cr`)).should("have.text", "5"); + cy.get(cesc(`#\\/sr`)).should("have.text", "3"); cy.get(cesc(`#\\/ca`)).should("have.text", "0"); cy.get(cesc("#\\/a_submit")).click(); @@ -1645,20 +1546,8 @@ describe("Answer Tag Tests", function () { cy.get(correctAnchor).should("be.visible"); cy.get(incorrectAnchor).should("not.exist"); - cy.get(cesc(`#\\/cr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc(`#\\/sr`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); + cy.get(cesc(`#\\/cr`)).should("have.text", "5"); + cy.get(cesc(`#\\/sr`)).should("have.text", "5"); cy.get(cesc(`#\\/ca`)).should("have.text", "1"); }); @@ -3109,7 +2998,7 @@ describe("Answer Tag Tests", function () { ); cy.get(cesc("#\\/x") + " textarea").blur(); - cy.get(cesc("#\\/pSubX") + " .mjx-mrow").should("contain.text", "y"); + cy.get(cesc("#\\/pSubX")).should("contain.text", "y"); cy.get(cesc("#\\/pCreditX")).should( "have.text", "Credit for this answer: 0", @@ -3122,7 +3011,7 @@ describe("Answer Tag Tests", function () { cy.get(cesc("#\\/x") + " textarea").type("{end}{backspace}x{enter}", { force: true, }); - cy.get(cesc("#\\/pSubX") + " .mjx-mrow").should("contain.text", "x"); + cy.get(cesc("#\\/pSubX")).should("contain.text", "x"); cy.get(cesc("#\\/pCreditX")).should( "have.text", "Credit for this answer: 1", @@ -3318,16 +3207,7 @@ describe("Answer Tag Tests", function () { "Credit for this answer: 0", ); - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow").should( - "contain.text", - "3", - ); - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow") - .eq(1) - .should("have.text", "−5"); + cy.get(cesc("#\\/pSubFirstQuad")).should("contain.text", "3, −5"); cy.get(cesc("#\\/pCreditFirstQuad")).should( "have.text", @@ -3346,16 +3226,7 @@ describe("Answer Tag Tests", function () { }); }); - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow").should( - "contain.text", - "9", - ); - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/pSubFirstQuad") + " .mjx-mrow") - .eq(1) - .should("have.text", "8"); + cy.get(cesc("#\\/pSubFirstQuad")).should("contain.text", "9, 8"); cy.get(cesc("#\\/pCreditFirstQuad")).should( "have.text", @@ -3405,8 +3276,8 @@ describe("Answer Tag Tests", function () { ); }); - cy.get(cesc("#\\/n_submit")).click(); - cy.get(cesc("#\\/n_correct")).should("be.visible"); + // cy.get(cesc("#\\/n_submit")).click(); + // cy.get(cesc("#\\/n_correct")).should("be.visible"); }); it("reload text answer without blurring or hitting enter", () => { diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/booleaninput.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/booleaninput.cy.js index 64579a8a3..5cd9463ed 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/booleaninput.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/booleaninput.cy.js @@ -149,7 +149,7 @@ describe("BooleanInput Tag Tests", function () { cy.get(cesc("#\\/atb_input")).should("not.be.checked"); cy.get(cesc("#\\/bi_input")).should("not.be.checked"); cy.get(cesc("#\\/v")).should("have.text", "false"); - cy.get(cesc("#\\/atb")).should("contain.text", "It is ∫baf(x)dx"); + cy.get(cesc("#\\/atb")).should("contain.text", "It is ∫abf(x)dx"); cy.get(cesc("#\\/bi")).should("contain.text", "Hello ab"); cy.log("Test internal values are set to the correct values"); @@ -174,7 +174,7 @@ describe("BooleanInput Tag Tests", function () { cy.get(cesc("#\\/atb_input")).should("be.checked"); // TODO: how to check the renderer if ToggleButton is selected //cy.get(cesc('#\\/bi_input')).should('be.checked'); - cy.get(cesc("#\\/atb")).should("contain.text", "It is ∫baf(x)dx"); + cy.get(cesc("#\\/atb")).should("contain.text", "It is ∫abf(x)dx"); cy.get(cesc("#\\/bi")).should("contain.text", "Hello ab"); cy.log("Test internal values are set to the correct values"); @@ -194,7 +194,7 @@ describe("BooleanInput Tag Tests", function () { cy.log("hide labels"); cy.get(cesc2("#/toggleLabels")).click(); - cy.get(cesc("#\\/atb")).should("not.contain.text", "It is ∫baf(x)dx"); + cy.get(cesc("#\\/atb")).should("not.contain.text", "It is ∫abf(x)dx"); cy.get(cesc("#\\/bi")).should("not.contain.text", "Hello ab"); cy.log("Test internal values are set to the correct values"); @@ -210,7 +210,7 @@ describe("BooleanInput Tag Tests", function () { cy.log("show labels again"); cy.get(cesc2("#/toggleLabels")).click(); - cy.get(cesc("#\\/atb")).should("contain.text", "It is ∫baf(x)dx"); + cy.get(cesc("#\\/atb")).should("contain.text", "It is ∫abf(x)dx"); cy.get(cesc("#\\/bi")).should("contain.text", "Hello ab"); cy.log("Test internal values are set to the correct values"); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/circle.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/circle.cy.js index 38d49096f..4f9f244f8 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/circle.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/circle.cy.js @@ -47,7 +47,7 @@ describe("Circle Tag Tests", function () { 0, 0, ]); expect(stateVariables["/circ"].stateValues.numericalRadius).eq(1); - cy.get(cesc(`#\\/r2`) + ` .mjx-mrow`).should("contain.text", "1"); + cy.get(cesc(`#\\/r2`)).should("contain.text", "1"); }); cy.log(`move circle`); @@ -58,8 +58,8 @@ describe("Circle Tag Tests", function () { args: { center: [-7, 2] }, }); - cy.get(cesc(`#\\/r2`) + ` .mjx-mrow`).should("contain.text", "1"); - cy.get(cesc(`#\\/c`) + ` .mjx-mrow`).should( + cy.get(cesc(`#\\/r2`)).should("contain.text", "1"); + cy.get(cesc(`#\\/c`)).should( "contain.text", `(${nInDOM(-7)},${nInDOM(2)})`, ); @@ -83,7 +83,7 @@ describe("Circle Tag Tests", function () { "contain.text", "3", ); - cy.get(cesc(`#\\/r2`) + ` .mjx-mrow`).should("contain.text", "3"); + cy.get(cesc(`#\\/r2`)).should("contain.text", "3"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/codeeditor.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/codeeditor.cy.js index f37c4182b..9c8400145 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/codeeditor.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/codeeditor.cy.js @@ -33,9 +33,7 @@ describe("Code Editor Tag Tests", function () { }); cy.log("type text in editor"); - cy.get(cesc("#\\/editor") + " .cm-content").type("Hello!", { - delay: 10, - }); + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke("text", "Hello!"); cy.get(cesc("#\\/_p1")).should("have.text", "Hello!"); cy.get(cesc("#\\/_p2")).should("have.text", ""); @@ -62,9 +60,11 @@ describe("Code Editor Tag Tests", function () { }); cy.log("type more in editor"); - cy.get(cesc("#\\/editor") + " .cm-content").type("{enter}More here.", { - delay: 10, - }); + cy.get(cesc("#\\/editor") + " .cm-activeLine").type("{enter}"); + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke( + "text", + "More here.", + ); cy.get(cesc("#\\/_p1")).should("have.text", "Hello!\nMore here."); cy.get(cesc("#\\/_p2")).should("have.text", "Hello!"); @@ -128,9 +128,11 @@ describe("Code Editor Tag Tests", function () { }); cy.log("type text in editor"); - cy.get(cesc("#\\/editor") + " .cm-content").type("

Hello!

", { - delay: 10, - }); + cy.get(cesc("#\\/editor") + " .cm-content").focus(); + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke( + "text", + "

Hello!

", + ); cy.get(cesc("#\\/_p1")).should("have.text", "

Hello!

"); cy.get(cesc("#\\/_p2")).should("have.text", ""); @@ -193,9 +195,13 @@ describe("Code Editor Tag Tests", function () { }); cy.log("type more content"); - cy.get(cesc("#\\/editor") + " .cm-content").type( - "{ctrl+end}{enter}

1+1

", - { delay: 10 }, + + cy.get(cesc("#\\/editor") + " .cm-activeLine").type( + "{ctrl+end}{enter}", + ); + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke( + "text", + "

1+1

", ); cy.get(cesc("#\\/_p1")).should( @@ -1247,7 +1253,7 @@ describe("Code Editor Tag Tests", function () { ); }); - cy.get(cesc("#\\/ce") + " .cm-content").type("hello", { delay: 10 }); + cy.get(cesc("#\\/ce") + " .cm-activeLine").invoke("text", "hello"); cy.get(cesc("#\\/piv")).should("have.text", "immediate value: hello"); cy.get(cesc("#\\/pv")).should("have.text", "value: "); @@ -1296,9 +1302,10 @@ describe("Code Editor Tag Tests", function () { cy.get(cesc2("#/_p1")).should("have.text", ""); cy.log("type text in editor"); - cy.get(cesc("#\\/editor") + " .cm-content").type("

Hello!

", { - delay: 10, - }); + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke( + "text", + "

Hello!

", + ); cy.get(`[data-test="Viewer Update Button"]`).click(); cy.get(cesc2("#/_p1")).should("have.text", "

Hello!

"); @@ -1322,29 +1329,19 @@ describe("Code Editor Tag Tests", function () { cy.log("Overwrite text"); - if (Cypress.platform === "darwin") { - cy.get(cesc("#\\/editor") + " .cm-content").type( - "{command+a}Ovewritten!", - { - delay: 10, - }, - ); - } else { - cy.get(cesc("#\\/editor") + " .cm-content").type( - "{control+a}Ovewritten!", - { - delay: 10, - }, - ); - } + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke( + "text", + "Overwritten!", + ); + cy.get(`[data-test="Viewer Update Button"]`).click(); cy.get(cesc2("#/_p1")).should( "have.text", - "Ovewritten!", + "Overwritten!", ); cy.get(cesc2("#/editor/_p1")).should("not.exist"); - cy.get(cesc2("#/editor/_alert1")).should("have.text", "Ovewritten!"); + cy.get(cesc2("#/editor/_alert1")).should("have.text", "Overwritten!"); cy.wait(1500); // wait for 1 second debounce @@ -1397,30 +1394,29 @@ describe("Code Editor Tag Tests", function () { cy.get(cesc2("#/_p1")).should("have.text", ""); cy.log("type text in editor"); - cy.get(cesc("#\\/editor") + " .cm-content").type("

Hello!

", { - delay: 10, - }); + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke( + "text", + "

Hello!

", + ); - // Note: for some reason, have to type {enter} more slowly cy.get(cesc("#\\/editor") + " .cm-content").type("{end}{enter}"); cy.get(`[data-test="Viewer Update Button"]`).click(); cy.get(cesc2("#/_p1")).should("have.text", "

Hello!

\n"); cy.get(cesc2("#/editor/_p1")).should("have.text", "Hello!"); - cy.get(cesc("#\\/editor") + " .cm-content").type( - "{ctrl+end}$ti", - { - delay: 10, - }, + cy.get(cesc("#\\/editor") + " .cm-activeLine").type("{ctrl+end}"); + + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke( + "text", + "$ti", ); - // Note: for some reason, have to type {enter} more slowly - cy.get(cesc("#\\/editor") + " .cm-content").type("{end}{enter}"); + cy.get(`[data-test="Viewer Update Button"]`).click(); cy.get(cesc2("#/_p1")).should( "have.text", - "

Hello!

\n$ti\n", + "

Hello!

\n$ti", ); cy.get(cesc2("#/editor-viewer")).should( @@ -1428,18 +1424,16 @@ describe("Code Editor Tag Tests", function () { "Circular dependency", ); - cy.get(cesc("#\\/editor") + " .cm-content").type( - "{ctrl+end}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}{backspace}Bye", - { - delay: 10, - }, + cy.get(cesc("#\\/editor") + " .cm-activeLine").invoke( + "text", + "Bye", ); cy.get(`[data-test="Viewer Update Button"]`).click(); cy.get(cesc2("#/_p1")).should( "have.text", - "

Hello!

\nBye\n", + "

Hello!

\nBye", ); cy.get(cesc2("#/editor/_p1")).should("have.text", "Hello!"); cy.get(cesc2("#/editor/ti")).should("have.text", "Bye"); @@ -1471,10 +1465,10 @@ describe("Code Editor Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("contain.text", "a"); cy.log("type text in editor 1"); - cy.get(cesc("#\\/editor1") + " .cm-content").type("

Apple

", { - delay: 10, - }); - // Note: for some reason, have to type {enter} more slowly + cy.get(cesc("#\\/editor1") + " .cm-activeLine").invoke( + "text", + "

Apple

", + ); cy.get(cesc("#\\/editor1") + " .cm-content").type("{end}{enter}"); cy.get( @@ -1486,10 +1480,10 @@ describe("Code Editor Tag Tests", function () { cy.get(cesc2("#/editor1/_p1")).should("contain.text", "Apple"); cy.log("type text in editor 2"); - cy.get(cesc("#\\/editor2") + " .cm-content").type("

Banana

", { - delay: 10, - }); - // Note: for some reason, have to type {enter} more slowly + cy.get(cesc("#\\/editor2") + " .cm-activeLine").invoke( + "text", + "

Banana

", + ); cy.get(cesc("#\\/editor2") + " .cm-content").type("{end}{enter}"); cy.get( cesc2("#/editor2-viewer-controls") + @@ -1500,10 +1494,10 @@ describe("Code Editor Tag Tests", function () { cy.get(cesc2("#/editor2/_p1")).should("contain.text", "Banana"); cy.log("type text in editor 3"); - cy.get(cesc("#\\/editor3") + " .cm-content").type("

Cherry

", { - delay: 10, - }); - // Note: for some reason, have to type {enter} more slowly + cy.get(cesc("#\\/editor3") + " .cm-activeLine").invoke( + "text", + "

Cherry

", + ); cy.get(cesc("#\\/editor3") + " .cm-content").type("{end}{enter}"); cy.get( cesc2("#/editor3-viewer-controls") + diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/contentBrowser.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/contentBrowser.cy.js index 8bc5cda63..f8a6109a4 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/contentBrowser.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/contentBrowser.cy.js @@ -99,9 +99,7 @@ describe("ContentBrowser Tag Tests", function () { .invoke("attr", "src") .then((src) => expect(src.includes("tJ4ypc5L6uU")).eq(true)); - cy.get(cesc2("#/mathp2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); + cy.get(cesc2("#/mathp2")).should("contain.text", "x+x"); cy.get(cesc2("#/mathinputp1")).should("not.exist"); cy.get(cesc2("#/mathinputp2")).should("not.exist"); @@ -303,9 +301,7 @@ describe("ContentBrowser Tag Tests", function () { .invoke("attr", "src") .then((src) => expect(src.includes("tJ4ypc5L6uU")).eq(true)); - cy.get(cesc2("#/mathp2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); + cy.get(cesc2("#/mathp2")).should("contain.text", "x+x"); cy.log("select unlabeled"); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/line.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/line.cy.js index a0f4592f6..a7651ca80 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/line.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/line.cy.js @@ -1,3 +1,5 @@ +import { cesc } from "@doenet/utils"; + describe("Line Tag Tests", function () { beforeEach(() => { cy.clearIndexedDB(); @@ -34,8 +36,8 @@ describe("Line Tag Tests", function () { // use this to wait for page to load cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/Ac") + " .mjx-mrow").should("contain.text", "(1,2)"); - cy.get(cesc("#\\/Bc") + " .mjx-mrow").should("contain.text", "(3,4)"); + cy.get(cesc("#\\/Ac")).should("contain.text", "(1,2)"); + cy.get(cesc("#\\/Bc")).should("contain.text", "(3,4)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -56,8 +58,8 @@ describe("Line Tag Tests", function () { }); }); - cy.get(cesc("#\\/Ac") + " .mjx-mrow").should("contain.text", "(9,8)"); - cy.get(cesc("#\\/Bc") + " .mjx-mrow").should("contain.text", "(6,7)"); + cy.get(cesc("#\\/Ac")).should("contain.text", "(9,8)"); + cy.get(cesc("#\\/Bc")).should("contain.text", "(6,7)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -89,8 +91,8 @@ describe("Line Tag Tests", function () { }), ); - cy.get(cesc("#\\/Ac") + " .mjx-mrow").should("contain.text", "(9,8)"); - cy.get(cesc("#\\/Bc") + " .mjx-mrow").should("contain.text", "(6,7)"); + cy.get(cesc("#\\/Ac")).should("contain.text", "(9,8)"); + cy.get(cesc("#\\/Bc")).should("contain.text", "(6,7)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -106,11 +108,8 @@ describe("Line Tag Tests", function () { }); }); - cy.get(cesc("#\\/Ac") + " .mjx-mrow").should( - "contain.text", - "(0.5,3.5)", - ); - cy.get(cesc("#\\/Bc") + " .mjx-mrow").should("contain.text", "(6,7)"); + cy.get(cesc("#\\/Ac")).should("contain.text", "(0.5,3.5)"); + cy.get(cesc("#\\/Bc")).should("contain.text", "(6,7)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -142,11 +141,8 @@ describe("Line Tag Tests", function () { }), ); - cy.get(cesc("#\\/Ac") + " .mjx-mrow").should( - "contain.text", - "(0.5,3.5)", - ); - cy.get(cesc("#\\/Bc") + " .mjx-mrow").should("contain.text", "(6,7)"); + cy.get(cesc("#\\/Ac")).should("contain.text", "(0.5,3.5)"); + cy.get(cesc("#\\/Bc")).should("contain.text", "(6,7)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -162,11 +158,8 @@ describe("Line Tag Tests", function () { }); }); - cy.get(cesc("#\\/Ac") + " .mjx-mrow").should( - "contain.text", - "(8.5,1.5)", - ); - cy.get(cesc("#\\/Bc") + " .mjx-mrow").should("contain.text", "(6,7)"); + cy.get(cesc("#\\/Ac")).should("contain.text", "(8.5,1.5)"); + cy.get(cesc("#\\/Bc")).should("contain.text", "(6,7)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/math.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/math.cy.js index 0f3e1d6f3..a8d9cc4d3 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/math.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/math.cy.js @@ -15,11 +15,11 @@ describe("Math Tag Tests", function () {

x + y

z

a+$m4

-

-

-

-

-

+

+

+

+

+

`; cy.get("#testRunner_toggleControls").click(); @@ -38,18 +38,10 @@ describe("Math Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "w"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+y"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+z"); + cy.get(cesc("#\\/m1")).should("have.text", "w"); + cy.get(cesc("#\\/m2")).should("have.text", "x+y"); + cy.get(cesc("#\\/m4")).should("have.text", "z"); + cy.get(cesc("#\\/m5")).should("have.text", "a+z"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -78,20 +70,12 @@ describe("Math Tag Tests", function () { force: true, }); - cy.get(cesc("#\\/m4") + " .mjx-mrow").should("contain.text", "3"); - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+2"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+3"); + cy.get(cesc("#\\/m4")).should("contain.text", "3"); + + cy.get(cesc("#\\/m1")).should("have.text", "1"); + cy.get(cesc("#\\/m2")).should("have.text", "x+2"); + cy.get(cesc("#\\/m4")).should("have.text", "3"); + cy.get(cesc("#\\/m5")).should("have.text", "a+3"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -125,18 +109,10 @@ describe("Math Tag Tests", function () { }), ); - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+2"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+3"); + cy.get(cesc("#\\/m1")).should("have.text", "1"); + cy.get(cesc("#\\/m2")).should("have.text", "x+2"); + cy.get(cesc("#\\/m4")).should("have.text", "3"); + cy.get(cesc("#\\/m5")).should("have.text", "a+3"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -166,20 +142,12 @@ describe("Math Tag Tests", function () { }, ); - cy.get(cesc("#\\/m5") + " .mjx-mrow").should("contain.text", "17"); - - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "4+5"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+6+7"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "17"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+17"); + cy.get(cesc("#\\/m5")).should("contain.text", "17"); + + cy.get(cesc("#\\/m1")).should("have.text", "4+5"); + cy.get(cesc("#\\/m2")).should("have.text", "x+6+7"); + cy.get(cesc("#\\/m4")).should("have.text", "17"); + cy.get(cesc("#\\/m5")).should("have.text", "a+17"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -222,18 +190,10 @@ describe("Math Tag Tests", function () { }), ); - cy.get(cesc("#\\/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "4+5"); - cy.get(cesc("#\\/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+6+7"); - cy.get(cesc("#\\/m4") + " .mjx-mrow") - .eq(0) - .should("have.text", "17"); - cy.get(cesc("#\\/m5") + " .mjx-mrow") - .eq(0) - .should("have.text", "a+17"); + cy.get(cesc("#\\/m1")).should("have.text", "4+5"); + cy.get(cesc("#\\/m2")).should("have.text", "x+6+7"); + cy.get(cesc("#\\/m4")).should("have.text", "17"); + cy.get(cesc("#\\/m5")).should("have.text", "a+17"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -266,7 +226,7 @@ describe("Math Tag Tests", function () { -

Style number:

+

Style number:

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

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

@@ -493,10 +453,10 @@ describe("Math Tag Tests", function () { let m1dName = stateVariables["/p2"].activeChildren[0].componentName; let m2dName = stateVariables["/p2"].activeChildren[2].componentName; - let m1cAnchor = "#" + cesc2(m1cName) + " .mjx-mrow"; - let m2cAnchor = "#" + cesc2(m2cName) + " .mjx-mrow"; - let m1dAnchor = "#" + cesc2(m1dName) + " .mjx-mrow"; - let m2dAnchor = "#" + cesc2(m2dName) + " .mjx-mrow"; + let m1cAnchor = "#" + cesc2(m1cName); + let m2cAnchor = "#" + cesc2(m2cName); + let m1dAnchor = "#" + cesc2(m1dName); + let m2dAnchor = "#" + cesc2(m2dName); cy.get(m1cAnchor).eq(0).should("have.text", "x2"); cy.get(m1dAnchor).eq(0).should("have.text", "x2"); @@ -508,24 +468,12 @@ describe("Math Tag Tests", function () { cy.get(m2cAnchor).should("have.css", "color", "rgb(255, 0, 0)"); cy.get(m2dAnchor).should("have.css", "color", "rgb(0, 0, 0)"); - cy.get(cesc("#\\/m1coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/m2coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc("#\\/m1acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/m2acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc("#\\/m1bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/m2bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); + cy.get(cesc("#\\/m1coords")).eq(0).should("have.text", "(0,0)"); + cy.get(cesc("#\\/m2coords")).eq(0).should("have.text", "(3,4)"); + cy.get(cesc("#\\/m1acoords")).eq(0).should("have.text", "(0,0)"); + cy.get(cesc("#\\/m2acoords")).eq(0).should("have.text", "(3,4)"); + cy.get(cesc("#\\/m1bcoords")).eq(0).should("have.text", "(0,0)"); + cy.get(cesc("#\\/m2bcoords")).eq(0).should("have.text", "(0,0)"); cy.log("move first maths"); cy.window().then(async (win) => { @@ -541,29 +489,14 @@ describe("Math Tag Tests", function () { }); }); - cy.get(cesc("#\\/m2coords") + " .mjx-mrow").should( - "contain.text", - "(4,−5)", - ); + cy.get(cesc("#\\/m2coords")).should("contain.text", "(4,−5)"); - cy.get(cesc("#\\/m1coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/m2coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - cy.get(cesc("#\\/m1acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/m2acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - cy.get(cesc("#\\/m1bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/m2bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); + cy.get(cesc("#\\/m1coords")).eq(0).should("have.text", "(−2,3)"); + cy.get(cesc("#\\/m2coords")).eq(0).should("have.text", "(4,−5)"); + cy.get(cesc("#\\/m1acoords")).eq(0).should("have.text", "(−2,3)"); + cy.get(cesc("#\\/m2acoords")).eq(0).should("have.text", "(4,−5)"); + cy.get(cesc("#\\/m1bcoords")).eq(0).should("have.text", "(0,0)"); + cy.get(cesc("#\\/m2bcoords")).eq(0).should("have.text", "(0,0)"); cy.log("move second maths"); cy.window().then(async (win) => { @@ -579,29 +512,14 @@ describe("Math Tag Tests", function () { }); }); - cy.get(cesc("#\\/m2coords") + " .mjx-mrow").should( - "contain.text", - "(−8,2)", - ); + cy.get(cesc("#\\/m2coords")).should("contain.text", "(−8,2)"); - cy.get(cesc("#\\/m1coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,1)"); - cy.get(cesc("#\\/m2coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,2)"); - cy.get(cesc("#\\/m1acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,1)"); - cy.get(cesc("#\\/m2acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,2)"); - cy.get(cesc("#\\/m1bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/m2bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); + cy.get(cesc("#\\/m1coords")).eq(0).should("have.text", "(7,1)"); + cy.get(cesc("#\\/m2coords")).eq(0).should("have.text", "(−8,2)"); + cy.get(cesc("#\\/m1acoords")).eq(0).should("have.text", "(7,1)"); + cy.get(cesc("#\\/m2acoords")).eq(0).should("have.text", "(−8,2)"); + cy.get(cesc("#\\/m1bcoords")).eq(0).should("have.text", "(0,0)"); + cy.get(cesc("#\\/m2bcoords")).eq(0).should("have.text", "(0,0)"); cy.log("move third maths"); cy.window().then(async (win) => { @@ -617,29 +535,14 @@ describe("Math Tag Tests", function () { }); }); - cy.get(cesc("#\\/m2bcoords") + " .mjx-mrow").should( - "contain.text", - "(−5,−4)", - ); + cy.get(cesc("#\\/m2bcoords")).should("contain.text", "(−5,−4)"); - cy.get(cesc("#\\/m1coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,1)"); - cy.get(cesc("#\\/m2coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,2)"); - cy.get(cesc("#\\/m1acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,1)"); - cy.get(cesc("#\\/m2acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,2)"); - cy.get(cesc("#\\/m1bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−6,3)"); - cy.get(cesc("#\\/m2bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−5,−4)"); + cy.get(cesc("#\\/m1coords")).eq(0).should("have.text", "(7,1)"); + cy.get(cesc("#\\/m2coords")).eq(0).should("have.text", "(−8,2)"); + cy.get(cesc("#\\/m1acoords")).eq(0).should("have.text", "(7,1)"); + cy.get(cesc("#\\/m2acoords")).eq(0).should("have.text", "(−8,2)"); + cy.get(cesc("#\\/m1bcoords")).eq(0).should("have.text", "(−6,3)"); + cy.get(cesc("#\\/m2bcoords")).eq(0).should("have.text", "(−5,−4)"); }); }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/mathdisplay.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/mathdisplay.cy.js index 1806227b8..42c20c735 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/mathdisplay.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/mathdisplay.cy.js @@ -34,27 +34,9 @@ describe("Math Display Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded cy.log("Test value displayed in browser"); - cy.get(cesc("#\\/e1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)(1)"); - }); - cy.get(cesc("#\\/e2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("cos(x)(2)"); - }); - cy.get(cesc("#\\/e3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("tan(x)(3)"); - }); + cy.get(cesc("#\\/e1")).should("have.text", "(1)sin⁡(x)"); + cy.get(cesc("#\\/e2")).should("have.text", "(2)cos⁡(x)"); + cy.get(cesc("#\\/e3")).should("have.text", "(3)tan⁡(x)"); cy.get(cesc("#\\/_p1")).should( "have.text", "We have equation (1), equation (2), and equation (3).", @@ -147,13 +129,7 @@ describe("Math Display Tag Tests", function () { function checkEquationNumbering(m, n) { let counter = 1; - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`x(${counter})`); - }); + cy.get(cesc("#\\/x")).should("have.text", `(${counter})x`); cy.get(cesc("#\\/px")).should( "have.text", `x: ${counter}, equation (${counter})`, @@ -169,13 +145,10 @@ describe("Math Display Tag Tests", function () { for (let i = 1; i <= m; i++) { cy.window().then(async (win) => { counter++; - cy.get(cesc(`#\\/m${i}\\/eq`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}m(${counter})`); - }); + cy.get(cesc(`#\\/m${i}\\/eq`)).should( + "have.text", + `(${counter})${i}m`, + ); if (i <= 6) { cy.get(cesc(`#\\/pm${i}`)).should( "have.text", @@ -214,13 +187,7 @@ describe("Math Display Tag Tests", function () { cy.window().then(async (win) => { counter++; - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`y(${counter})`); - }); + cy.get(cesc("#\\/y")).should("have.text", `(${counter})y`); cy.get(cesc("#\\/py")).should( "have.text", `y: ${counter}, equation (${counter})`, @@ -237,13 +204,10 @@ describe("Math Display Tag Tests", function () { for (let i = 1; i <= n; i++) { cy.window().then(async (win) => { counter++; - cy.get(cesc(`#\\/n${i}\\/eq`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}n(${counter})`); - }); + cy.get(cesc(`#\\/n${i}\\/eq`)).should( + "have.text", + `(${counter})${i}n`, + ); if (i <= 6) { cy.get(cesc(`#\\/pn${i}`)).should( "have.text", @@ -283,13 +247,7 @@ describe("Math Display Tag Tests", function () { cy.window().then(async (win) => { counter++; - cy.get(cesc("#\\/z")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`z(${counter})`); - }); + cy.get(cesc("#\\/z")).should("have.text", `(${counter})z`); cy.get(cesc("#\\/pz")).should( "have.text", `z: ${counter}, equation (${counter})`, @@ -401,13 +359,7 @@ describe("Math Display Tag Tests", function () { function checkEquationNumbering(m, n) { let counter = 1; - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`x(${counter})`); - }); + cy.get(cesc("#\\/x")).should("have.text", `(${counter})x`); cy.get(cesc("#\\/px")).should( "have.text", `x: ${counter}, equation (${counter})`, @@ -420,23 +372,18 @@ describe("Math Display Tag Tests", function () { expect(rect.top).gt(-1).lt(5); }); + cy.window().then(async (win) => { + cy.get(cesc("#\\/ms")).should( + "have.text", + [...Array(m).keys()] + .map((v) => v + 1) + .map((i) => `(${counter + i})${i}m=${i + 10}`) + .join(""), + ); + }); for (let i = 1; i <= m; i++) { cy.window().then(async (win) => { counter++; - cy.get(cesc("#\\/ms")) - .find(".mjx-mlabeledtr") - .eq(i - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}m=${i + 10}`); - }); - cy.get(cesc("#\\/ms")) - .find(".mjx-label") - .eq(i - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(${counter})`); - }); if (i <= 6) { cy.get(cesc(`#\\/pm${i}`)).should( "have.text", @@ -475,13 +422,7 @@ describe("Math Display Tag Tests", function () { cy.window().then(async (win) => { counter++; - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`y(${counter})`); - }); + cy.get(cesc("#\\/y")).should("have.text", `(${counter})y`); cy.get(cesc("#\\/py")).should( "have.text", `y: ${counter}, equation (${counter})`, @@ -495,23 +436,19 @@ describe("Math Display Tag Tests", function () { }); }); + cy.window().then(async (win) => { + cy.get(cesc("#\\/ns")).should( + "have.text", + [...Array(n).keys()] + .map((v) => v + 1) + .map((i) => `(${counter + i})${i}n=${i + 10}`) + .join(""), + ); + }); + for (let i = 1; i <= n; i++) { cy.window().then(async (win) => { counter++; - cy.get(cesc("#\\/ns")) - .find(".mjx-mlabeledtr") - .eq(i - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}n=${i + 10}`); - }); - cy.get(cesc("#\\/ns")) - .find(".mjx-label") - .eq(i - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(${counter})`); - }); if (i <= 6) { cy.get(cesc(`#\\/pn${i}`)).should( "have.text", @@ -551,13 +488,7 @@ describe("Math Display Tag Tests", function () { cy.window().then(async (win) => { counter++; - cy.get(cesc("#\\/z")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`z(${counter})`); - }); + cy.get(cesc("#\\/z")).should("have.text", `(${counter})z`); cy.get(cesc("#\\/pz")).should( "have.text", `z: ${counter}, equation (${counter})`, @@ -669,13 +600,7 @@ describe("Math Display Tag Tests", function () { function checkEquationNumbering(m, n) { let counter = 1; - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`x(${counter})`); - }); + cy.get(cesc("#\\/x")).should("have.text", `(${counter})x`); cy.get(cesc("#\\/px")).should( "have.text", `x: ${counter}, equation (${counter})`, @@ -691,25 +616,14 @@ describe("Math Display Tag Tests", function () { let labeledMs = 0; let unlabeledMs = 0; + let mPieces = []; for (let i = 1; i <= m; i++) { cy.window().then(async (win) => { if (i % 2 === 1) { labeledMs++; counter++; - cy.get(cesc("#\\/ms")) - .find(".mjx-mlabeledtr") - .eq(labeledMs - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}m=${i + 10}`); - }); - cy.get(cesc("#\\/ms")) - .find(".mjx-label") - .eq(i - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(${counter})`); - }); + mPieces.push(`(${counter})${i}m=${i + 10}`); + if (i <= 6) { cy.get(cesc(`#\\/pm${i}`)).should( "have.text", @@ -735,13 +649,8 @@ describe("Math Display Tag Tests", function () { } } else { unlabeledMs++; - cy.get(cesc("#\\/ms")) - .find(".mjx-mtr") - .eq(unlabeledMs - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}m=${i + 10}`); - }); + mPieces.push(`${i}m=${i + 10}`); + if (i <= 6) { cy.get(cesc(`#\\/pm${i}`)).should( "have.text", @@ -761,6 +670,10 @@ describe("Math Display Tag Tests", function () { } }); } + cy.window().then(async (win) => { + cy.get(cesc("#\\/ms")).should("have.text", mPieces.join("")); + }); + for (let i = m + 1; i <= 6; i++) { cy.window().then(async (win) => { cy.get(cesc(`#\\/pm${i}`)).should( @@ -779,13 +692,7 @@ describe("Math Display Tag Tests", function () { cy.window().then(async (win) => { counter++; - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`y(${counter})`); - }); + cy.get(cesc("#\\/y")).should("have.text", `(${counter})y`); cy.get(cesc("#\\/py")).should( "have.text", `y: ${counter}, equation (${counter})`, @@ -802,25 +709,13 @@ describe("Math Display Tag Tests", function () { let labeledNs = 0; let unlabeledNs = 0; + let nPieces = []; for (let i = 1; i <= n; i++) { cy.window().then(async (win) => { if (i % 2 === 0) { labeledNs++; counter++; - cy.get(cesc("#\\/ns")) - .find(".mjx-mlabeledtr") - .eq(labeledNs - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}n=${i + 10}`); - }); - cy.get(cesc("#\\/ns")) - .find(".mjx-label") - .eq(i - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`(${counter})`); - }); + nPieces.push(`(${counter})${i}n=${i + 10}`); if (i <= 6) { cy.get(cesc(`#\\/pn${i}`)).should( "have.text", @@ -846,13 +741,7 @@ describe("Math Display Tag Tests", function () { } } else { unlabeledNs++; - cy.get(cesc("#\\/ns")) - .find(".mjx-mtr") - .eq(unlabeledNs - 1) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}n=${i + 10}`); - }); + nPieces.push(`${i}n=${i + 10}`); if (i <= 6) { cy.get(cesc(`#\\/pn${i}`)).should( "have.text", @@ -873,6 +762,10 @@ describe("Math Display Tag Tests", function () { }); } + cy.window().then(async (win) => { + cy.get(cesc("#\\/ns")).should("have.text", nPieces.join("")); + }); + for (let i = n + 1; i <= 6; i++) { cy.window().then(async (win) => { cy.get(cesc(`#\\/pn${i}`)).should( @@ -891,13 +784,7 @@ describe("Math Display Tag Tests", function () { cy.window().then(async (win) => { counter++; - cy.get(cesc("#\\/z")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`z(${counter})`); - }); + cy.get(cesc("#\\/z")).should("have.text", `(${counter})z`); cy.get(cesc("#\\/pz")).should( "have.text", `z: ${counter}, equation (${counter})`, diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/mathinput.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/mathinput.cy.js index da13ce717..453280ecb 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/mathinput.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/mathinput.cy.js @@ -23,7 +23,7 @@ describe("MathInput Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "_"); + cy.get(cesc("#\\/a2")).should("contain.text", "_"); cy.get(cesc("#\\/a") + " textarea").type("sqrt4{enter}", { force: true, @@ -33,8 +33,8 @@ describe("MathInput Tag Tests", function () { "contain.text", "√4", ); - cy.get(cesc("#\\/a2") + " .mjx-mrow").should("contain.text", "√4"); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "2"); + cy.get(cesc("#\\/a2")).should("contain.text", "4"); + cy.get(cesc("#\\/a3")).should("contain.text", "2"); cy.get(cesc("#\\/a") + " .mq-editable-field") .invoke("text") @@ -43,20 +43,6 @@ describe("MathInput Tag Tests", function () { "√4", ); }); - cy.get(cesc("#\\/a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√4"); - }); - cy.get(cesc("#\\/a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); }); it("check ignoreUpdate bug 1", () => { @@ -116,7 +102,7 @@ describe("MathInput Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/c2") + " .mjx-mrow") + cy.get(cesc("#\\/c2")) .eq(0) .invoke("text") .then((text) => { @@ -133,7 +119,7 @@ describe("MathInput Tag Tests", function () { "contain.text", "xy", ); - cy.get(cesc("#\\/c2") + " .mjx-mrow") + cy.get(cesc("#\\/c2")) .eq(0) .invoke("text") .then((text) => { @@ -149,7 +135,7 @@ describe("MathInput Tag Tests", function () { "contain.text", "x", ); - cy.get(cesc("#\\/c2") + " .mjx-mrow") + cy.get(cesc("#\\/c2")) .eq(0) .invoke("text") .then((text) => { @@ -181,13 +167,8 @@ describe("MathInput Tag Tests", function () { cy.get(cesc("#\\/n") + " textarea").type("1", { force: true }); - cy.get(cesc("#\\/piv") + " .mjx-mrow").should("contain.text", "1"); - cy.get(cesc("#\\/piv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/pv") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); + cy.get(cesc("#\\/piv")).should("have.text", "immediate value: 1"); + cy.get(cesc("#\\/pv")).should("contain.text", "value: \uff3f"); cy.wait(1500); // wait for debounce @@ -202,13 +183,8 @@ describe("MathInput Tag Tests", function () { ); }); - cy.get(cesc("#\\/pv") + " .mjx-mrow").should("contain.text", "1"); - cy.get(cesc("#\\/piv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/pv") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); + cy.get(cesc("#\\/pv")).should("have.text", "value: 1"); + cy.get(cesc("#\\/piv")).should("have.text", "immediate value: 1"); }); it("minWidth attribute", () => { @@ -256,7 +232,7 @@ describe("MathInput Tag Tests", function () { cy.get(cesc("#\\/result") + " .mq-editable-field").should( "have.css", "min-width", - "0px", + "50px", ); cy.get(cesc("#\\/mw") + " textarea").type("{end}{backspace}40{enter}", { @@ -274,7 +250,7 @@ describe("MathInput Tag Tests", function () { cy.get(cesc("#\\/result") + " .mq-editable-field").should( "have.css", "min-width", - "0px", + "50px", ); cy.get(cesc("#\\/mw") + " textarea").type( diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/matrixinput.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/matrixinput.cy.js index 0964a1ca6..2b070fe16 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/matrixinput.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/matrixinput.cy.js @@ -30,13 +30,8 @@ describe("MatrixInput Tag Tests", function () { cy.get(cesc("#\\/n") + " textarea").type("1", { force: true }); - cy.get(cesc("#\\/piv") + " .mjx-mrow").should("contain.text", "[1]"); - cy.get(cesc("#\\/piv") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/pv") + " .mjx-mrow") - .eq(0) - .should("have.text", "[\uff3f]"); + cy.get(cesc("#\\/piv")).should("have.text", "immediate value: [1]"); + cy.get(cesc("#\\/pv")).should("contain.text", "[\uff3f]"); cy.wait(1500); // wait for debounce @@ -51,12 +46,7 @@ describe("MatrixInput Tag Tests", function () { ); }); - cy.get(cesc("#\\/pv") + " .mjx-mrow").should("contain.text", "[1]"); - cy.get(cesc("#\\/piv") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); - cy.get(cesc("#\\/pv") + " .mjx-mrow") - .eq(0) - .should("have.text", "[1]"); + cy.get(cesc("#\\/pv")).should("have.text", "value: [1]"); + cy.get(cesc("#\\/piv")).should("have.text", "immediate value: [1]"); }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/module.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/module.cy.js index 4ddcc8aa1..facb76ef3 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/module.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/module.cy.js @@ -37,49 +37,13 @@ describe("Module Tag Tests", function () { }); cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - cy.get(cesc2(`#/m1/_m1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(3,4)"); - }); - cy.get(cesc(`#\\/coordsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(-3,3)"); - }); - cy.get(cesc(`#\\/coordsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,-5)"); - }); - cy.get(cesc2(`#/m2/_m1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,-5)"); - }); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("_"); - }); + cy.get(cesc2(`#/m1/_m1`)).should("have.text", "(3,4)"); + cy.get(cesc(`#\\/coordsa`)).should("have.text", "(−3,3)"); + cy.get(cesc(`#\\/coordsb`)).should("have.text", "(7,−5)"); + cy.get(cesc2(`#/m2/_m1`)).should("have.text", "(7,−5)"); + cy.get(cesc("#\\/sr1")).should("contain.text", "_"); cy.get(cesc("#\\/ca1")).should("have.text", "0"); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("_"); - }); + cy.get(cesc("#\\/sr2")).should("contain.text", "_"); cy.get(cesc("#\\/ca2")).should("have.text", "0"); cy.window().then(async (win) => { @@ -93,21 +57,9 @@ describe("Module Tag Tests", function () { cy.get(cesc2("#/m1/ans_submit")).click(); cy.get(cesc2("#/m2/ans_submit")).click(); cy.get(cesc("#\\/sr2")).should("contain.text", "(−3,3)"); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(0,0)"); - }); + cy.get(cesc("#\\/sr1")).should("have.text", "(0,0)"); cy.get(cesc("#\\/ca1")).should("have.text", "0"); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(-3,3)"); - }); + cy.get(cesc("#\\/sr2")).should("have.text", "(−3,3)"); cy.get(cesc("#\\/ca2")).should("have.text", "0"); cy.log("move near correct answers"); @@ -124,55 +76,19 @@ describe("Module Tag Tests", function () { }); }); - cy.get(cesc2(`#/m1/_m1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(3,4)"); - }); - cy.get(cesc(`#\\/coordsa`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(-3,3)"); - }); - cy.get(cesc(`#\\/coordsb`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,-5)"); - }); - cy.get(cesc2(`#/m2/_m1`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,-5)"); - }); + cy.get(cesc2(`#/m1/_m1`)).should("have.text", "(3,4)"); + cy.get(cesc(`#\\/coordsa`)).should("have.text", "(−3,3)"); + cy.get(cesc(`#\\/coordsb`)).should("have.text", "(7,−5)"); + cy.get(cesc2(`#/m2/_m1`)).should("have.text", "(7,−5)"); cy.log("submit answers"); cy.get(cesc2("#/m1/ans_submit")).click(); cy.get(cesc2("#/m2/ans_submit")).click(); cy.get(cesc("#\\/sr2")).should("contain.text", "(7,−5)"); - cy.get(cesc("#\\/sr1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(3,4)"); - }); + cy.get(cesc("#\\/sr1")).should("have.text", "(3,4)"); cy.get(cesc("#\\/ca1")).should("have.text", "1"); - cy.get(cesc("#\\/sr2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,-5)"); - }); + cy.get(cesc("#\\/sr2")).should("have.text", "(7,−5)"); cy.get(cesc("#\\/ca2")).should("have.text", "1"); }); @@ -215,94 +131,22 @@ describe("Module Tag Tests", function () { let mediumWidth = 425; let largeWidth = 595; - cy.get(cesc2("#/g/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); - cy.get(cesc2("#/g/_m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3"); - }); - cy.get(cesc2("#/g/extMod/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); - cy.get(cesc2("#/g/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("_"); - }); + cy.get(cesc2("#/g/_m1")).should("have.text", "(1,2)"); + cy.get(cesc2("#/g/_m3")).should("have.text", "3"); + cy.get(cesc2("#/g/extMod/_m1")).should("have.text", "(1,2)"); + cy.get(cesc2("#/g/sr")).should("contain.text", "_"); cy.get(cesc2("#/g/ca")).should("have.text", "0"); - cy.get(cesc2("#/g2/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); - cy.get(cesc2("#/g2/_m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("9"); - }); - cy.get(cesc2("#/g2/extMod/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); - cy.get(cesc2("#/g2/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("_"); - }); + cy.get(cesc2("#/g2/_m1")).should("have.text", "(1,−5)"); + cy.get(cesc2("#/g2/_m3")).should("have.text", "9"); + cy.get(cesc2("#/g2/extMod/_m1")).should("have.text", "(1,−5)"); + cy.get(cesc2("#/g2/sr")).should("contain.text", "_"); cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.get(cesc2("#/g3/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); - cy.get(cesc2("#/g3/_m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("-3"); - }); - cy.get(cesc2("#/g3/extMod/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); - cy.get(cesc2("#/g3/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("_"); - }); + cy.get(cesc2("#/g3/_m1")).should("have.text", "(7,2)"); + cy.get(cesc2("#/g3/_m3")).should("have.text", "−3"); + cy.get(cesc2("#/g3/extMod/_m1")).should("have.text", "(7,2)"); + cy.get(cesc2("#/g3/sr")).should("contain.text", "_"); cy.get(cesc2("#/g3/ca")).should("have.text", "0"); cy.window().then(async (win) => { @@ -347,29 +191,11 @@ describe("Module Tag Tests", function () { cy.get(cesc2("#/g3/sr")).should("contain.text", "(−3,0)"); - cy.get(cesc2("#/g/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(3,0)"); - }); + cy.get(cesc2("#/g/sr")).should("have.text", "(3,0)"); cy.get(cesc2("#/g/ca")).should("have.text", "0"); - cy.get(cesc2("#/g2/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(9,0)"); - }); + cy.get(cesc2("#/g2/sr")).should("have.text", "(9,0)"); cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.get(cesc2("#/g3/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(-3,0)"); - }); + cy.get(cesc2("#/g3/sr")).should("have.text", "(−3,0)"); cy.get(cesc2("#/g3/ca")).should("have.text", "0"); cy.log("move near correct answers"); @@ -391,94 +217,22 @@ describe("Module Tag Tests", function () { }); }); - cy.get(cesc2("#/g/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); - cy.get(cesc2("#/g/_m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3"); - }); - cy.get(cesc2("#/g/extMod/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); - cy.get(cesc2("#/g/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(3,0)"); - }); + cy.get(cesc2("#/g/_m1")).should("have.text", "(1,2)"); + cy.get(cesc2("#/g/_m3")).should("have.text", "3"); + cy.get(cesc2("#/g/extMod/_m1")).should("have.text", "(1,2)"); + cy.get(cesc2("#/g/sr")).should("have.text", "(3,0)"); cy.get(cesc2("#/g/ca")).should("have.text", "0"); - cy.get(cesc2("#/g2/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); - cy.get(cesc2("#/g2/_m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("9"); - }); - cy.get(cesc2("#/g2/extMod/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); - cy.get(cesc2("#/g2/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(9,0)"); - }); + cy.get(cesc2("#/g2/_m1")).should("have.text", "(1,−5)"); + cy.get(cesc2("#/g2/_m3")).should("have.text", "9"); + cy.get(cesc2("#/g2/extMod/_m1")).should("have.text", "(1,−5)"); + cy.get(cesc2("#/g2/sr")).should("have.text", "(9,0)"); cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.get(cesc2("#/g3/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); - cy.get(cesc2("#/g3/_m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("-3"); - }); - cy.get(cesc2("#/g3/extMod/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); - cy.get(cesc2("#/g3/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(-3,0)"); - }); + cy.get(cesc2("#/g3/_m1")).should("have.text", "(7,2)"); + cy.get(cesc2("#/g3/_m3")).should("have.text", "−3"); + cy.get(cesc2("#/g3/extMod/_m1")).should("have.text", "(7,2)"); + cy.get(cesc2("#/g3/sr")).should("have.text", "(−3,0)"); cy.get(cesc2("#/g3/ca")).should("have.text", "0"); cy.log("submit answers"); @@ -489,29 +243,11 @@ describe("Module Tag Tests", function () { cy.get(cesc2("#/g3/sr")).should("contain.text", "(7,2)"); - cy.get(cesc2("#/g/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); + cy.get(cesc2("#/g/sr")).should("have.text", "(1,2)"); cy.get(cesc2("#/g/ca")).should("have.text", "1"); - cy.get(cesc2("#/g2/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); + cy.get(cesc2("#/g2/sr")).should("have.text", "(1,−5)"); cy.get(cesc2("#/g2/ca")).should("have.text", "1"); - cy.get(cesc2("#/g3/sr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); + cy.get(cesc2("#/g3/sr")).should("have.text", "(7,2)"); cy.get(cesc2("#/g3/ca")).should("have.text", "1"); }); @@ -635,69 +371,15 @@ describe("Module Tag Tests", function () { "_incorrect", ); - cy.get(cesc2("#/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); - cy.get(cesc2("#/_m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3"); - }); - cy.get(cesc2("#/extMod/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); - cy.get(g2m1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); - cy.get(g2m3Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("9"); - }); - cy.get(g2extm1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); - cy.get(g3m1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); - cy.get(g3m3Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("-3"); - }); - cy.get(g3extm1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); + cy.get(cesc2("#/_m1")).should("have.text", "(1,2)"); + cy.get(cesc2("#/_m3")).should("have.text", "3"); + cy.get(cesc2("#/extMod/_m1")).should("have.text", "(1,2)"); + cy.get(g2m1Anchor).should("have.text", "(1,−5)"); + cy.get(g2m3Anchor).should("have.text", "9"); + cy.get(g2extm1Anchor).should("have.text", "(1,−5)"); + cy.get(g3m1Anchor).should("have.text", "(7,2)"); + cy.get(g3m3Anchor).should("have.text", "−3"); + cy.get(g3extm1Anchor).should("have.text", "(7,2)"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -779,69 +461,15 @@ describe("Module Tag Tests", function () { }); }); - cy.get(cesc2("#/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); - cy.get(cesc2("#/_m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3"); - }); - cy.get(cesc2("#/extMod/_m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,2)"); - }); - cy.get(g2m1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); - cy.get(g2m3Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("9"); - }); - cy.get(g2extm1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(1,-5)"); - }); - cy.get(g3m1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); - cy.get(g3m3Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("-3"); - }); - cy.get(g3extm1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("(7,2)"); - }); + cy.get(cesc2("#/_m1")).should("have.text", "(1,2)"); + cy.get(cesc2("#/_m3")).should("have.text", "3"); + cy.get(cesc2("#/extMod/_m1")).should("have.text", "(1,2)"); + cy.get(g2m1Anchor).should("have.text", "(1,−5)"); + cy.get(g2m3Anchor).should("have.text", "9"); + cy.get(g2extm1Anchor).should("have.text", "(1,−5)"); + cy.get(g3m1Anchor).should("have.text", "(7,2)"); + cy.get(g3m3Anchor).should("have.text", "−3"); + cy.get(g3extm1Anchor).should("have.text", "(7,2)"); cy.log("submit answers"); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/point.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/point.cy.js index e4642dff4..a1f84eadb 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/point.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/point.cy.js @@ -39,9 +39,7 @@ describe("Point Tag Tests 2", function () { ); }); - cy.get(cesc2("#/P0a") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); + cy.get(cesc2("#/P0a")).should("have.text", "(3,4)"); cy.log("move point using skippable actions to upper right"); let promises = []; @@ -73,13 +71,7 @@ describe("Point Tag Tests 2", function () { }); }); - cy.get(cesc2("#/P0a") + " .mjx-mrow").should( - "contain.text", - "(9.9,9.9)", - ); - cy.get(cesc2("#/P0a") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9.9,9.9)"); + cy.get(cesc2("#/P0a")).should("have.text", "(9.9,9.9)"); cy.log( "move point using skippable and non-skippable actions to upper left", @@ -121,12 +113,6 @@ describe("Point Tag Tests 2", function () { }); }); - cy.get(cesc2("#/P0a") + " .mjx-mrow").should( - "contain.text", - "(−9.9,9.9)", - ); - cy.get(cesc2("#/P0a") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−9.9,9.9)"); + cy.get(cesc2("#/P0a")).should("have.text", "(−9.9,9.9)"); }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/sectioning.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/sectioning.cy.js index de5e76b50..913ef4702 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/sectioning.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/sectioning.cy.js @@ -34,25 +34,10 @@ describe("Sectioning Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - cy.get(cesc("#\\/expr1b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x+1)(x2−1)"); - }); - cy.get(cesc("#\\/expr2b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x−1)(x2+1)"); - }); + cy.get(cesc("#\\/expr1b")).should("have.text", "(x+1)(x2−1)"); + cy.get(cesc("#\\/expr2b")).should("have.text", "(x−1)(x2+1)"); cy.get(cesc("#\\/expr1a")).should("not.exist"); - cy.get(cesc("#\\/expr2a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x−1)(x2+1)"); - }); + cy.get(cesc("#\\/expr2a")).should("have.text", "(x−1)(x2+1)"); cy.get(cesc("#\\/expr1")).should("not.exist"); cy.get(cesc("#\\/expr2") + " .mq-editable-field") @@ -63,12 +48,7 @@ describe("Sectioning Tag Tests", function () { cy.get(cesc("#\\/aside1_title")).click(); - cy.get(cesc("#\\/expr1a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x+1)(x2−1)"); - }); + cy.get(cesc("#\\/expr1a")).should("have.text", "(x+1)(x2−1)"); cy.get(cesc("#\\/expr1") + " .mq-editable-field") .invoke("text") .then((text) => { @@ -79,30 +59,15 @@ describe("Sectioning Tag Tests", function () { cy.get(cesc("#\\/expr2a")).should("not.exist"); cy.get(cesc("#\\/expr2")).should("not.exist"); - cy.get(cesc("#\\/expr1b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x+1)(x2−1)"); - }); - cy.get(cesc("#\\/expr2b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x−1)(x2+1)"); - }); + cy.get(cesc("#\\/expr1b")).should("have.text", "(x+1)(x2−1)"); + cy.get(cesc("#\\/expr2b")).should("have.text", "(x−1)(x2+1)"); cy.get(cesc("#\\/expr1") + " textarea") .type("{end}{leftArrow}{backspace}4{enter}", { force: true }) .blur(); cy.get(cesc("#\\/expr1a")).should("contain.text", "(x+1)(x2−4)"); - cy.get(cesc("#\\/expr1a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x+1)(x2−4)"); - }); + cy.get(cesc("#\\/expr1a")).should("have.text", "(x+1)(x2−4)"); cy.get(cesc("#\\/expr1") + " .mq-editable-field") .invoke("text") .then((text) => { @@ -111,44 +76,19 @@ describe("Sectioning Tag Tests", function () { ); }); - cy.get(cesc("#\\/expr1b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x+1)(x2−4)"); - }); - cy.get(cesc("#\\/expr2b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x−1)(x2+1)"); - }); + cy.get(cesc("#\\/expr1b")).should("have.text", "(x+1)(x2−4)"); + cy.get(cesc("#\\/expr2b")).should("have.text", "(x−1)(x2+1)"); cy.get(cesc("#\\/aside1_title")).click(); cy.get(cesc("#\\/expr1a")).should("not.exist"); cy.get(cesc("#\\/expr1")).should("not.exist"); - cy.get(cesc("#\\/expr1b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x+1)(x2−4)"); - }); - cy.get(cesc("#\\/expr2b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x−1)(x2+1)"); - }); + cy.get(cesc("#\\/expr1b")).should("have.text", "(x+1)(x2−4)"); + cy.get(cesc("#\\/expr2b")).should("have.text", "(x−1)(x2+1)"); cy.get(cesc("#\\/aside2_title")).click(); - cy.get(cesc("#\\/expr2a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x−1)(x2+1)"); - }); + cy.get(cesc("#\\/expr2a")).should("have.text", "(x−1)(x2+1)"); cy.get(cesc("#\\/expr2") + " .mq-editable-field") .invoke("text") .then((text) => { @@ -159,12 +99,7 @@ describe("Sectioning Tag Tests", function () { .type("{end}{leftArrow}{backspace}4{enter}", { force: true }) .blur(); - cy.get(cesc("#\\/expr2a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x−1)(x2+4)"); - }); + cy.get(cesc("#\\/expr2a")).should("have.text", "(x−1)(x2+4)"); cy.get(cesc("#\\/expr2") + " .mq-editable-field") .invoke("text") .then((text) => { @@ -173,18 +108,8 @@ describe("Sectioning Tag Tests", function () { ); }); - cy.get(cesc("#\\/expr1b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x+1)(x2−4)"); - }); - cy.get(cesc("#\\/expr2b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(x−1)(x2+4)"); - }); + cy.get(cesc("#\\/expr1b")).should("have.text", "(x+1)(x2−4)"); + cy.get(cesc("#\\/expr2b")).should("have.text", "(x−1)(x2+4)"); }); it("copy and overwrite title", () => { diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/selectfromsequence.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/selectfromsequence.cy.js index 4d3323107..2bbcd5971 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/selectfromsequence.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/selectfromsequence.cy.js @@ -100,11 +100,11 @@ describe("SelectFromSequence Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "\uff3f"); + cy.get(cesc("#\\/m")).should("contain.text", "\uff3f"); cy.get(cesc("#\\/mi") + " textarea").type("x{enter}", { force: true }); - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "x"); - cy.get(cesc("#\\/m2") + " .mjx-mrow").should("contain.text", "x"); + cy.get(cesc("#\\/m")).should("contain.text", "x"); + cy.get(cesc("#\\/m2")).should("contain.text", "x"); cy.wait(2000); // wait for debounce @@ -121,17 +121,17 @@ describe("SelectFromSequence Tag Tests", function () { cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "x"); + cy.get(cesc("#\\/m")).should("contain.text", "x"); cy.log("core has not crashed and processes change in bi"); cy.get(cesc("#\\/mi") + " textarea") .type("{end}{backspace}y", { force: true }) .blur(); - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "y"); + cy.get(cesc("#\\/m")).should("contain.text", "y"); cy.get(cesc("#\\/mi") + " textarea").type("{enter}", { force: true }); - cy.get(cesc("#\\/m") + " .mjx-mrow").should("contain.text", "y"); - cy.get(cesc("#\\/m2") + " .mjx-mrow").should("contain.text", "y"); + cy.get(cesc("#\\/m")).should("contain.text", "y"); + cy.get(cesc("#\\/m2")).should("contain.text", "y"); }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/slider.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/slider.cy.js index 25339aa5d..61c8e55a6 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/slider.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/slider.cy.js @@ -367,8 +367,7 @@ describe("Slider Tag Tests", function () { cy.get(cesc("#\\/sv")).should("have.text", "0"); - cy.get(cesc("#\\/s-label")).should("contain.text", "Hello x2"); - cy.get(cesc("#\\/s-label")).should("contain.text", "x^2 = 0"); + cy.get(cesc("#\\/s-label")).should("contain.text", "Hello x2 = 0"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); @@ -387,8 +386,7 @@ describe("Slider Tag Tests", function () { cy.get(cesc("#\\/sv")).should("have.text", "1"); - cy.get(cesc("#\\/s-label")).should("contain.text", "Hello x2"); - cy.get(cesc("#\\/s-label")).should("contain.text", "x^2 = 1"); + cy.get(cesc("#\\/s-label")).should("contain.text", "Hello x2 = 1"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/spreadsheet.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/spreadsheet.cy.js index 600f70178..216c2f98b 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/spreadsheet.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/spreadsheet.cy.js @@ -1140,50 +1140,50 @@ describe("Spreadsheet Tag Tests", function () { let c3 = "(5,6)"; let c4 = "(7,8)"; - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c1); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c1); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c3); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c3); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c2); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c4); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c2); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c4); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); }); it("copy propIndex of points in cells, dot and array notation", () => { @@ -1218,50 +1218,50 @@ describe("Spreadsheet Tag Tests", function () { let c3 = "(5,6)"; let c4 = "(7,8)"; - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c1); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c1); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c3); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c3); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c2); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c4); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c2); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c4); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); }); it("copy multidimensional propIndex of points in cells, dot and array notation", () => { @@ -1296,50 +1296,50 @@ describe("Spreadsheet Tag Tests", function () { let c3 = "(5,6)"; let c4 = "(7,8)"; - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c1); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c1); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c3); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c3); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c2); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c4); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c2); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c4); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); }); it("copy multidimensional propIndex of points in rows and columns, dot and array notation", () => { @@ -1374,50 +1374,50 @@ describe("Spreadsheet Tag Tests", function () { let c3 = "(5,6)"; let c4 = "(7,8)"; - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c1); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c1); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c3); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c3); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c2); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c4); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c2); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c4); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); }); it("copy single propIndex of points in rows and columns, dot and array notation", () => { @@ -1452,49 +1452,49 @@ describe("Spreadsheet Tag Tests", function () { let c3 = "(5,6)"; let c4 = "(7,8)"; - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c1); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("contain.text", c2); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c1); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c1); + cy.get(cesc("#\\/P2")).should("contain.text", c2); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c1); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c3); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c3); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("contain.text", c4); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c3); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c3); + cy.get(cesc("#\\/P5")).should("contain.text", c4); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("contain.text", c4); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", c2); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("contain.text", c4); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("contain.text", c2); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { force: true, }); - cy.get(cesc("#\\/P1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P5") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/P6") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/P1")).should("not.exist"); + cy.get(cesc("#\\/P2")).should("not.exist"); + cy.get(cesc("#\\/P3")).should("not.exist"); + cy.get(cesc("#\\/P4")).should("not.exist"); + cy.get(cesc("#\\/P5")).should("not.exist"); + cy.get(cesc("#\\/P6")).should("not.exist"); }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/text.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/text.cy.js index 760074ed4..a9627b038 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/text.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/text.cy.js @@ -260,24 +260,12 @@ describe("Text Tag Tests", function () { cy.get(t2cAnchor).should("have.css", "color", "rgb(255, 0, 0)"); cy.get(t2dAnchor).should("have.css", "color", "rgb(0, 0, 0)"); - cy.get(cesc("#\\/t1coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/t2coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc("#\\/t1acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/t2acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc("#\\/t1bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/t2bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); + cy.get(cesc("#\\/t1coords")).should("have.text", "(0,0)"); + cy.get(cesc("#\\/t2coords")).should("have.text", "(3,4)"); + cy.get(cesc("#\\/t1acoords")).should("have.text", "(0,0)"); + cy.get(cesc("#\\/t2acoords")).should("have.text", "(3,4)"); + cy.get(cesc("#\\/t1bcoords")).should("have.text", "(0,0)"); + cy.get(cesc("#\\/t2bcoords")).should("have.text", "(0,0)"); cy.log("move first texts"); cy.window().then(async (win) => { @@ -293,29 +281,14 @@ describe("Text Tag Tests", function () { }); }); - cy.get(cesc("#\\/t2coords") + " .mjx-mrow").should( - "contain.text", - "(4,−5)", - ); + cy.get(cesc("#\\/t2coords")).should("contain.text", "(4,−5)"); - cy.get(cesc("#\\/t1coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/t2coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - cy.get(cesc("#\\/t1acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/t2acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - cy.get(cesc("#\\/t1bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/t2bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); + cy.get(cesc("#\\/t1coords")).should("have.text", "(−2,3)"); + cy.get(cesc("#\\/t2coords")).should("have.text", "(4,−5)"); + cy.get(cesc("#\\/t1acoords")).should("have.text", "(−2,3)"); + cy.get(cesc("#\\/t2acoords")).should("have.text", "(4,−5)"); + cy.get(cesc("#\\/t1bcoords")).should("have.text", "(0,0)"); + cy.get(cesc("#\\/t2bcoords")).should("have.text", "(0,0)"); cy.log("move second texts"); cy.window().then(async (win) => { @@ -331,29 +304,14 @@ describe("Text Tag Tests", function () { }); }); - cy.get(cesc("#\\/t2coords") + " .mjx-mrow").should( - "contain.text", - "(−8,2)", - ); + cy.get(cesc("#\\/t2coords")).should("contain.text", "(−8,2)"); - cy.get(cesc("#\\/t1coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,1)"); - cy.get(cesc("#\\/t2coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,2)"); - cy.get(cesc("#\\/t1acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,1)"); - cy.get(cesc("#\\/t2acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,2)"); - cy.get(cesc("#\\/t1bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc("#\\/t2bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); + cy.get(cesc("#\\/t1coords")).should("have.text", "(7,1)"); + cy.get(cesc("#\\/t2coords")).should("have.text", "(−8,2)"); + cy.get(cesc("#\\/t1acoords")).should("have.text", "(7,1)"); + cy.get(cesc("#\\/t2acoords")).should("have.text", "(−8,2)"); + cy.get(cesc("#\\/t1bcoords")).should("have.text", "(0,0)"); + cy.get(cesc("#\\/t2bcoords")).should("have.text", "(0,0)"); cy.log("move third texts"); cy.window().then(async (win) => { @@ -369,29 +327,14 @@ describe("Text Tag Tests", function () { }); }); - cy.get(cesc("#\\/t2bcoords") + " .mjx-mrow").should( - "contain.text", - "(−5,−4)", - ); + cy.get(cesc("#\\/t2bcoords")).should("contain.text", "(−5,−4)"); - cy.get(cesc("#\\/t1coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,1)"); - cy.get(cesc("#\\/t2coords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,2)"); - cy.get(cesc("#\\/t1acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,1)"); - cy.get(cesc("#\\/t2acoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,2)"); - cy.get(cesc("#\\/t1bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−6,3)"); - cy.get(cesc("#\\/t2bcoords") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−5,−4)"); + cy.get(cesc("#\\/t1coords")).should("have.text", "(7,1)"); + cy.get(cesc("#\\/t2coords")).should("have.text", "(−8,2)"); + cy.get(cesc("#\\/t1acoords")).should("have.text", "(7,1)"); + cy.get(cesc("#\\/t2acoords")).should("have.text", "(−8,2)"); + cy.get(cesc("#\\/t1bcoords")).should("have.text", "(−6,3)"); + cy.get(cesc("#\\/t2bcoords")).should("have.text", "(−5,−4)"); }); }); }); diff --git a/packages/test-cypress/src/CypressTest.tsx b/packages/test-cypress/src/CypressTest.tsx index 410990863..b5edd9dd2 100644 --- a/packages/test-cypress/src/CypressTest.tsx +++ b/packages/test-cypress/src/CypressTest.tsx @@ -18,7 +18,7 @@ export function CypressTest() { allowSaveSubmissions: boolean; allowSaveEvents: boolean; autoSubmit: boolean; - paginate: boolean; + render: boolean; darkMode: "light" | "dark"; showEditor: boolean; viewerLocation: "left" | "right" | "bottom" | "top"; @@ -36,7 +36,7 @@ export function CypressTest() { allowSaveSubmissions: false, allowSaveEvents: false, autoSubmit: false, - paginate: true, + render: true, darkMode: "light", showEditor: false, viewerLocation: "right", @@ -89,7 +89,7 @@ export function CypressTest() { testSettings.allowSaveEvents, ); const [autoSubmit, setAutoSubmit] = useState(testSettings.autoSubmit); - const [paginate, setPaginate] = useState(testSettings.paginate); + const [render, setRender] = useState(testSettings.render); const [showEditor, setShowEditor] = useState(testSettings.showEditor); const [viewerLocation, setViewerLocation] = useState( @@ -210,8 +210,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setShowCorrectness((was) => !was); - setUpdateNumber((was) => was + 1); + setShowCorrectness((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Show Correctness @@ -230,8 +230,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setReadOnly((was) => !was); - setUpdateNumber((was) => was + 1); + setReadOnly((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Read Only @@ -251,8 +251,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setShowFeedback((was) => !was); - setUpdateNumber((was) => was + 1); + setShowFeedback((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Show Feedback @@ -272,8 +272,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setShowHints((was) => !was); - setUpdateNumber((was) => was + 1); + setShowHints((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Show Hints @@ -294,8 +294,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setAllowLoadState((was) => !was); - setUpdateNumber((was) => was + 1); + setAllowLoadState((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Allow Load Page State @@ -315,8 +315,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setAllowSaveState((was) => !was); - setUpdateNumber((was) => was + 1); + setAllowSaveState((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Allow Save Page State @@ -336,8 +336,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setAllowLocalState((was) => !was); - setUpdateNumber((was) => was + 1); + setAllowLocalState((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Allow Local Page State @@ -357,8 +357,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setAllowSaveSubmissions((was) => !was); - setUpdateNumber((was) => was + 1); + setAllowSaveSubmissions((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Allow Save Submissions @@ -378,8 +378,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setAllowSaveEvents((was) => !was); - setUpdateNumber((was) => was + 1); + setAllowSaveEvents((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Allow Save Events @@ -399,8 +399,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setAutoSubmit((was) => !was); - setUpdateNumber((was) => was + 1); + setAutoSubmit((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Auto Submit Answers @@ -411,20 +411,20 @@ export function CypressTest() {
@@ -459,8 +459,8 @@ export function CypressTest() { "test settings", JSON.stringify(testSettings), ); - setShowEditor((was) => !was); - setUpdateNumber((was) => was + 1); + setShowEditor((was: boolean) => !was); + setUpdateNumber((was: number) => was + 1); }} /> Show Editor @@ -478,7 +478,7 @@ export function CypressTest() { JSON.stringify(testSettings), ); setViewerLocation(e.target.value); - setUpdateNumber((was) => was + 1); + setUpdateNumber((was: number) => was + 1); }} > @@ -494,13 +494,11 @@ export function CypressTest() { let editorOrViewer: React.JSX.Element | null = null; - console.log("type of doenetMLstring", typeof doenetMLstring); if (typeof doenetMLstring === "string") { const editor = ( setControlsVisible((was) => !was)} + onClick={() => + setControlsVisible((was: boolean) => !was) + } value={buttonText + " controls"} style={{ marginLeft: "12px" }} /> diff --git a/packages/test-viewer/src/test/testViewer.tsx b/packages/test-viewer/src/test/testViewer.tsx index 7a2ca18eb..691ee5b40 100644 --- a/packages/test-viewer/src/test/testViewer.tsx +++ b/packages/test-viewer/src/test/testViewer.tsx @@ -12,7 +12,7 @@ export default function TestViewer() { readOnly: boolean; showFeedback: boolean; showHints: boolean; - paginate: boolean; + render: boolean; showEditor: boolean; viewerLocation: "left" | "right" | "bottom" | "top"; } = { @@ -21,7 +21,7 @@ export default function TestViewer() { readOnly: false, showFeedback: true, showHints: true, - paginate: true, + render: true, showEditor: false, viewerLocation: "right", }; @@ -36,7 +36,7 @@ export default function TestViewer() { readOnly, showFeedback, showHints, - paginate, + render, showEditor, viewerLocation, } = testSettings; @@ -140,17 +140,17 @@ export default function TestViewer() { {" "} { setTestSettings((was) => { let newObj = { ...was }; - newObj.paginate = !was.paginate; + newObj.render = !was.render; return newObj; }); setUpdateNumber((was) => was + 1); }} /> - Paginate + Render
@@ -199,7 +199,6 @@ export default function TestViewer() { ); diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index a7bae5550..5145295aa 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -2,7 +2,6 @@ export * from "./ast/logging"; export * from "./ast/ast"; export * from "./errors/errorWarning"; export * from "./media/cid"; -export * from "./media/retrieveMedia"; export * from "./media/retrieveTextFile"; export * from "./copy/deepFunctions"; export * from "./copy/parseStringify"; diff --git a/packages/utils/src/math/math.ts b/packages/utils/src/math/math.ts index 1e741e296..b4a7ac52e 100644 --- a/packages/utils/src/math/math.ts +++ b/packages/utils/src/math/math.ts @@ -1,27 +1,7 @@ export const mathjaxConfig = { - showProcessingMessages: false, - "fast-preview": { - disabled: true, - }, - jax: ["input/TeX", "output/CommonHTML"], - extensions: [ - "tex2jax.js", - "MathMenu.js", - "MathZoom.js", - "AssistiveMML.js", - "a11y/accessibility-menu.js", - ], - TeX: { - extensions: [ - "AMSmath.js", - "AMSsymbols.js", - "noErrors.js", - "noUndefined.js", - ], - equationNumbers: { - autoNumber: "AMS", - }, - Macros: { + tex: { + tags: "ams", + macros: { lt: "<", gt: ">", amp: "&", @@ -29,8 +9,14 @@ export const mathjaxConfig = { csch: "\\operatorname{csch}", sech: "\\operatorname{sech}", }, - }, - tex2jax: { displayMath: [["\\[", "\\]"]], + packages: ["base", "ams", "noerrors", "noundefined", "configmacros"], + }, + options: { + ignoreHtmlClass: "tex2jax_ignore", + processHtmlClass: "tex2jax_process", + }, + loader: { + load: ["[tex]/noerrors"], }, }; diff --git a/packages/utils/src/media/retrieveMedia.ts b/packages/utils/src/media/retrieveMedia.ts deleted file mode 100644 index d22d46b4c..000000000 --- a/packages/utils/src/media/retrieveMedia.ts +++ /dev/null @@ -1,106 +0,0 @@ -import axios from "axios"; -import { cidFromArrayBuffer } from "./cid"; - -export async function retrieveMediaForCid( - cid: string, - mimeType: string, - useIPFS = false, -) { - if (useIPFS) { - try { - return await retrieveMediaFromIPFS(cid); - } catch (e) { - // if have error from IPFS, fallback to retrieving from server - } - } - - //Only if doenetML tag is not providing mimeType and not on IPFS - //look up in database - if (!mimeType) { - let { data } = await axios.get("/api/getMimeType.php", { - params: { cid: cid }, - }); - mimeType = data["mime-type"]; - } - - return retrieveMediaFromServer(cid, mimeType); -} - -async function retrieveMediaFromIPFS(cid: string) { - let controller = new AbortController(); - let signal = controller.signal; - - // If the IPFS gateway cannot find the cid, - // it hangs for a long time before timing out. - // To avoid the long wait, abort the request after 1 second. - let timeoutId = setTimeout(() => { - controller.abort(); - }, 1000); - - try { - let response = await fetch(`https://${cid}.ipfs.dweb.link/`, { - signal, - }); - - // if got a response, then we won't abort - clearTimeout(timeoutId); - - if (response.ok) { - let mediaBlob = await response.blob(); - - let CidRetrieved = await cidFromArrayBuffer( - await mediaBlob.arrayBuffer(), - ); - - if (CidRetrieved === cid) { - let mediaURL = URL.createObjectURL(mediaBlob); - return { mediaBlob, mediaURL }; - } else { - return Promise.reject(new Error("cid mismatch")); - } - } else { - return Promise.reject(new Error(`cid not found: ${cid}`)); - } - } catch (e) { - return Promise.reject(new Error(`cid not found: ${cid}`)); - } -} - -async function retrieveMediaFromServer(cid: string, mimeType: string) { - try { - let extension = extensionFromMimeType(mimeType); - - let response = await fetch(`/media/${cid}.${extension}`); - - if (response.ok) { - let mediaBlob = await response.blob(); - - let CidRetrieved = await cidFromArrayBuffer( - await mediaBlob.arrayBuffer(), - ); - - if (CidRetrieved === cid) { - let mediaURL = URL.createObjectURL(mediaBlob); - return { mediaBlob, mediaURL }; - } else { - return Promise.reject(new Error("cid mismatch")); - } - } else { - return Promise.reject(new Error(`cid not found: ${cid}`)); - } - } catch (e) { - return Promise.reject(new Error(`cid not found: ${cid}`)); - } -} - -function extensionFromMimeType(mimeType: string) { - if (mimeType === "image/png") { - return "png"; - } else if (mimeType === "image/jpeg") { - return "jpg"; - } else if (mimeType === "text/csv") { - return "csv"; - } else { - return "txt"; - } -}