From bfa693cdefb01ae61c2655e6eb85c0e0220effd3 Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Thu, 23 Feb 2023 07:12:29 -0600 Subject: [PATCH 1/4] new math features: altvectors, new symbols, functions --- .../answerValidation/matchpartial.cy.js | 40 + .../DoenetML/equality/mathexpressions.cy.js | 256 + .../e2e/DoenetML/tagSpecific/evaluate.cy.js | 10 +- .../e2e/DoenetML/tagSpecific/function.cy.js | 53 + .../tagSpecific/functioniterates.cy.js | 65 + cypress/e2e/DoenetML/tagSpecific/math.cy.js | 452 +- .../DoenetML/tagSpecific/matrixinput.cy.js | 5300 ++++++++++++++--- cypress/e2e/DoenetML/tagSpecific/point.cy.js | 151 +- cypress/e2e/DoenetML/tagSpecific/ray.cy.js | 155 + cypress/e2e/DoenetML/tagSpecific/vector.cy.js | 301 + package-lock.json | 499 +- package.json | 2 +- src/Core/Core.js | 15 + .../DiscreteSimulationResultList.js | 2 +- .../DiscreteSimulationResultPolyline.js | 2 +- src/Core/components/Evaluate.js | 2 +- src/Core/components/Function.js | 14 +- src/Core/components/FunctionIterates.js | 2 +- src/Core/components/Math.js | 30 +- src/Core/components/MatrixInput.js | 36 +- src/Core/components/Point.js | 6 +- src/Core/components/Ray.js | 6 +- src/Core/components/Spreadsheet.js | 2 +- src/Core/components/Vector.js | 26 +- src/Core/utils/checkEquality.js | 6 +- src/Core/utils/function.js | 12 +- src/Core/utils/math.js | 32 +- src/Viewer/renderers/mathInput.jsx | 19 +- 28 files changed, 6597 insertions(+), 899 deletions(-) create mode 100644 cypress/e2e/DoenetML/equality/mathexpressions.cy.js diff --git a/cypress/e2e/DoenetML/answerValidation/matchpartial.cy.js b/cypress/e2e/DoenetML/answerValidation/matchpartial.cy.js index 788c591a88..59545d50e8 100644 --- a/cypress/e2e/DoenetML/answerValidation/matchpartial.cy.js +++ b/cypress/e2e/DoenetML/answerValidation/matchpartial.cy.js @@ -4437,6 +4437,26 @@ describe('Match partial validation tests', function () { expect(text.trim().toLowerCase()).equal('50% correct') }) + cy.log("Submit first as altvector") + cy.get('#\\/mi textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 1,2\\rangle{enter}", { force: true, delay: 0 }) + cy.get('#\\/ans1_submit').click(); + cy.get('#\\/ans2_submit').click(); + + cy.get('#\\/ans1_partial').invoke('text').then((text) => { + expect(text.trim().toLowerCase()).equal('50% correct') + }) + cy.get('#\\/ans2_partial').invoke('text').then((text) => { + expect(text.trim().toLowerCase()).equal('50% correct') + }) + + + cy.log("Submit both as alt vectors") + cy.get('#\\/mi textarea').type("{end},\\langle 3,4\\rangle{enter}", { force: true, delay: 0 }) + cy.get('#\\/ans1_submit').click(); + cy.get('#\\/ans2_submit').click(); + + cy.get('#\\/ans1_correct').should('be.visible') + cy.get('#\\/ans2_correct').should('be.visible') }); @@ -4502,7 +4522,27 @@ describe('Match partial validation tests', function () { expect(text.trim().toLowerCase()).equal('50% correct') }) + cy.log("Submit first as altvector") + cy.get('#\\/mi textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 1,2\\rangle{enter}", { force: true, delay: 0 }) + cy.get('#\\/ans1_submit').click(); + cy.get('#\\/ans2_submit').click(); + + cy.get('#\\/ans1_partial').invoke('text').then((text) => { + expect(text.trim().toLowerCase()).equal('50% correct') + }) + cy.get('#\\/ans2_partial').invoke('text').then((text) => { + expect(text.trim().toLowerCase()).equal('50% correct') + }) + + + + cy.log("Submit both as altvectors") + cy.get('#\\/mi textarea').type("{end},\\langle 3,4\\rangle{enter}", { force: true, delay: 0 }) + cy.get('#\\/ans1_submit').click(); + cy.get('#\\/ans2_submit').click(); + cy.get('#\\/ans1_correct').should('be.visible') + cy.get('#\\/ans2_correct').should('be.visible') }); diff --git a/cypress/e2e/DoenetML/equality/mathexpressions.cy.js b/cypress/e2e/DoenetML/equality/mathexpressions.cy.js new file mode 100644 index 0000000000..4eb867ac57 --- /dev/null +++ b/cypress/e2e/DoenetML/equality/mathexpressions.cy.js @@ -0,0 +1,256 @@ +import cssesc from 'cssesc'; + +function cesc(s) { + s = cssesc(s, { isIdentifier: true }); + if (s.slice(0, 2) === '\\#') { + s = s.slice(1); + } + return s; +} + +describe('Math expressions equality tests', function () { + + beforeEach(() => { + cy.clearIndexedDB(); + cy.visit('/cypressTest') + }) + + it('inverse trig', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ sin^(-1)(x) = arcsin(x) + sin^(-1)(x) = asin(x) + sin^(-1)(1) = pi/2 + cos^(-1)(x) = arccos(x) + cos^(-1)(x) = acos(x) + cos^(-1)(1) = 0 + tan^(-1)(x) = arctan(x) + tan^(-1)(x) = atan(x) + tan^(-1)(1) = pi/4 +

+ +

+ sin^(-1)(x) = sin(x)^(-1) + cos^(-1)(x) = cos(x)^(-1) + tan^(-1)(x) = tan(x)^(-1) +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + let nTrues = 6, nFalses = 2; + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + + + it('trig shortcut powers, not other functions', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ sin^2(x) = sin(x)^2 + sin^n(x) = sin(x)^n + cos^2(x) = cos(x)^2 + cos^n(x) = cos(x)^n + tan^2(x) = tan(x)^2 + tan^n(x) = tan(x)^n + cos^2(x) = cos(x)^2 + cos^n(x) = cos(x)^n + sec^2(x) = sec(x)^2 + sec^n(x) = sec(x)^n + cot^2(x) = cot(x)^2 + cot^n(x) = cot(x)^n +

+ +

+ log^2(x) = log(x)^2 + log^n(x) = log(x)^n + ln^2(x) = ln(x)^2 + ln^n(x) = ln(x)^n + f^2(x) = f(x)^2 + f^n(x) = f(x)^n +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + let nTrues = 12, nFalses = 6; + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + + it('logarithms of different bases', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ log(e^3) = 3 + ln(e^3) = 3 + log10(10^3) = 3 + log_10(10^3) = 3 + log_2(2^3) = 3 + log_7(7^3) = 3 + log_b(a) = log(a)/log(b) +

+ + + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + let nTrues = 7, nFalses = 0; + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + + it('permutations and combinations', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ nCr(5,3) = 10 + nPr(5,3) = 60 + binom(5,3) = 10 +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + let nTrues = 3, nFalses = 0; + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + + it('alternative vectors', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + + ⟨a,b⟩ +

+ ⟨a,b⟩ = (a,b) + ⟨a,b⟩ = (a,b) + (a,b) = (a,b) +

+ +

+ ⟨a,b⟩ = (a,b) + (a,b) = (a,b) +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + let nTrues = 3, nFalses = 2; + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + + +}) \ No newline at end of file diff --git a/cypress/e2e/DoenetML/tagSpecific/evaluate.cy.js b/cypress/e2e/DoenetML/tagSpecific/evaluate.cy.js index 2f4c7697fb..76fe584e31 100644 --- a/cypress/e2e/DoenetML/tagSpecific/evaluate.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/evaluate.cy.js @@ -2056,8 +2056,8 @@ describe('Evaluate Tag Tests', function () { expect(stateVariables['/result7d'].stateValues.value).eqls(['/', ['^', '_', 2], ['^', '_', 3]]); }) - cy.log(`change inputs`); - cy.get('#\\/input1 textarea').type('{end}{leftArrow}{backspace}{backspace}{backspace}-3,5', { force: true }) + cy.log(`change inputs, use altvector`); + cy.get('#\\/input1 textarea').type('{ctrl+home}{shift+end}{backspace}\\langle -3,5\\rangle{enter}', { force: true }) cy.get('#\\/input2Orig textarea').type('{ctrl+home}{shift+end}{backspace}-3,5', { force: true }) cy.get('#\\/input4a textarea').type('{end}{backspace}-3', { force: true }) cy.get('#\\/input4b textarea').type('{end}{backspace}5', { force: true }).blur() @@ -2226,7 +2226,7 @@ describe('Evaluate Tag Tests', function () { cy.get('#\\/input1 textarea').type("{end}{backspace}pi{enter}", { force: true }); cy.get('#\\/input2 textarea').type("{end}{backspace}2pi{enter}", { force: true }); - cy.get('#\\/result_symbolic').should('contain.text','(sin(π+2π),cos(π−2π))') + cy.get('#\\/result_symbolic').should('contain.text', '(sin(π+2π),cos(π−2π))') cy.get('#\\/result_symbolic').find('.mjx-mrow').eq(0).invoke('text').then((text) => { expect(text.trim()).equal('(sin(π+2π),cos(π−2π))') }) @@ -2268,7 +2268,7 @@ describe('Evaluate Tag Tests', function () { cy.log('change variable') cy.get('#\\/variable1 textarea').type("{end}{backspace}u{enter}", { force: true }); cy.get('#\\/variable2 textarea').type("{end}{backspace}v{enter}", { force: true }); - cy.get('#\\/result_symbolic').should('contain.text','(sin(x+y),cos(x−y))') + cy.get('#\\/result_symbolic').should('contain.text', '(sin(x+y),cos(x−y))') cy.get('#\\/result_symbolic').find('.mjx-mrow').eq(0).invoke('text').then((text) => { expect(text.trim()).equal('(sin(x+y),cos(x−y))') }) @@ -2314,7 +2314,7 @@ describe('Evaluate Tag Tests', function () { cy.log('change formula to use new variables') cy.get('#\\/formula textarea').type("{end}{leftArrow}{leftArrow}{backspace}{backspace}{backspace}u-v{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}{backspace}u+v{enter}", { force: true }); - cy.get('#\\/result_symbolic').should('contain.text','(sin(π+2π),cos(π−2π))') + cy.get('#\\/result_symbolic').should('contain.text', '(sin(π+2π),cos(π−2π))') cy.get('#\\/result_symbolic').find('.mjx-mrow').eq(0).invoke('text').then((text) => { expect(text.trim()).equal('(sin(π+2π),cos(π−2π))') diff --git a/cypress/e2e/DoenetML/tagSpecific/function.cy.js b/cypress/e2e/DoenetML/tagSpecific/function.cy.js index 66f756ce27..1cc0c1cc6f 100644 --- a/cypress/e2e/DoenetML/tagSpecific/function.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/function.cy.js @@ -5923,6 +5923,59 @@ describe('Function Tag Tests', function () { }) }) + it('3D vector-valued function of two variables, as alt vector', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + ⟨s^2t^3, s^3t^2, st⟩ + `}, "*"); + }); + + //wait for window to load + cy.get('#\\/_text1').should('have.text', 'a'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables['/_function1'].stateValues.nInputs).eq(2); + expect(stateVariables['/_function1'].stateValues.nOutputs).eq(3); + + let f1 = createFunctionFromDefinition(stateVariables['/_function1'].stateValues.fDefinition, 0); + let f2 = createFunctionFromDefinition(stateVariables['/_function1'].stateValues.fDefinition, 1); + let f3 = createFunctionFromDefinition(stateVariables['/_function1'].stateValues.fDefinition, 2); + // let numericalf1 = (stateVariables['/_function1'].stateValues.numericalfs)[0]; + // let numericalf2 = (stateVariables['/_function1'].stateValues.numericalfs)[1]; + // let numericalf3 = (stateVariables['/_function1'].stateValues.numericalfs)[2]; + // let symbolicf1 = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; + // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; + // let symbolicf3 = (stateVariables['/_function1'].stateValues.symbolicfs)[2]; + + expect(f1(-5, 2)).closeTo(200, 1E-12); + expect(f2(-5, 2)).closeTo(-500, 1E-12); + expect(f3(-5, 2)).closeTo(-10, 1E-12); + expect(f1(3, -4)).closeTo(-576, 1E-12); + expect(f2(3, -4)).closeTo(432, 1E-12); + expect(f3(3, -4)).closeTo(-12, 1E-12); + // expect(numericalf1(-5, 2)).closeTo(200, 1E-12); + // expect(numericalf2(-5, 2)).closeTo(-500, 1E-12); + // expect(numericalf3(-5, 2)).closeTo(-10, 1E-12); + // expect(numericalf1(3, -4)).closeTo(-576, 1E-12); + // expect(numericalf2(3, -4)).closeTo(432, 1E-12); + // expect(numericalf3(3, -4)).closeTo(-12, 1E-12); + // expect(symbolicf1(-5, 2).equals(me.fromText('(-5)^2*2^3'))).eq(true); + // expect(symbolicf2(-5, 2).equals(me.fromText('(-5)^3*2^2'))).eq(true); + // expect(symbolicf3(-5, 2).equals(me.fromText('(-5)*2'))).eq(true); + // expect(symbolicf1(3, -4).equals(me.fromText('3^2*(-4)^3'))).eq(true); + // expect(symbolicf2(3, -4).equals(me.fromText('3^3*(-4)^2'))).eq(true); + // expect(symbolicf3(3, -4).equals(me.fromText('3*(-4)'))).eq(true); + // expect(symbolicf1('z', 'w').equals(me.fromText('z^2w^3'))).eq(true); + // expect(symbolicf2('z', 'w').equals(me.fromText('z^3w^2'))).eq(true); + // expect(symbolicf3('z', 'w').equals(me.fromText('zw'))).eq(true); + + + }) + }) + it('copy function and overwrite symbolic attribute', () => { cy.window().then(async (win) => { win.postMessage({ diff --git a/cypress/e2e/DoenetML/tagSpecific/functioniterates.cy.js b/cypress/e2e/DoenetML/tagSpecific/functioniterates.cy.js index f6dba95b4b..3e1f1a61d5 100644 --- a/cypress/e2e/DoenetML/tagSpecific/functioniterates.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/functioniterates.cy.js @@ -348,6 +348,71 @@ describe('FunctionIterates Tag Tests', function () { checkIterates({ a: -4, b: 7, c: 6, d: -1, u1: -8, u2: 9, n: 5 }) + }) + + it('2D linear function, with alt vectors', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

variables: and . + a = , b = , c = , d = . + f($x, $y) = ⟨$a$x+$b$y, $c$x+$d$y⟩ + u = n=

+ + +

Iterates:

+ + + `}, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait for page to load + + + function checkIterates({ a, b, c, d, u1, u2, n }) { + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + + let A = me.math.matrix([[a, b], [c, d]]); + let x = me.math.matrix([[u1], [u2]]); + + let iterNames = stateVariables["/iterates"].replacements.map(x => x.componentName); + let iterAnchors = iterNames.map(x => cesc('#' + x)) + + + for (let i = 0; i < n; i++) { + x = me.math.multiply(A, x); + let x1 = me.math.subset(x, me.math.index(0, 0)); + let x2 = me.math.subset(x, me.math.index(1, 0)); + expect(stateVariables[iterNames[i]].stateValues.value).eqls(["vector", x1, x2]) + cy.get(iterAnchors[i]).find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.replace(/−/g, '-')).equal(`(${x1},${x2})`) + }) + } + + + }); + } + + checkIterates({ a: 3, b: -2, c: 1, d: 4, u1: 2, u2: 1, n: 3 }) + + cy.log(`change values`) + cy.get('#\\/x textarea').type("{end}{backspace}q{enter}", { force: true }) + cy.get('#\\/y textarea').type("{end}{backspace}r{enter}", { force: true }) + cy.get('#\\/a textarea').type("{end}{backspace}{backspace}-4{enter}", { force: true }) + cy.get('#\\/b textarea').type("{end}{backspace}{backspace}7{enter}", { force: true }) + cy.get('#\\/c textarea').type("{end}{backspace}{backspace}6{enter}", { force: true }) + cy.get('#\\/d textarea').type("{end}{backspace}{backspace}-1{enter}", { force: true }) + cy.get('#\\/u textarea').type("{end}{leftArrow}{backspace}{backspace}{backspace}-8, 9{enter}", { force: true }) + cy.get('#\\/n textarea').type("{end}{backspace}5{enter}", { force: true }) + + cy.get('#\\/n2').should('contain.text', '5') + + checkIterates({ a: -4, b: 7, c: 6, d: -1, u1: -8, u2: 9, n: 5 }) + + }) it('change dimensions', () => { diff --git a/cypress/e2e/DoenetML/tagSpecific/math.cy.js b/cypress/e2e/DoenetML/tagSpecific/math.cy.js index 7bdb0c7558..535c283cc4 100644 --- a/cypress/e2e/DoenetML/tagSpecific/math.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/math.cy.js @@ -623,13 +623,14 @@ describe('Math Tag Tests', function () {

Create vectors: (1,2,3),(4,5),[6,7],(8,9],[10,11)

Create intervals: (1,2,3),(4,5),[6,7],(8,9],[10,11)

Create vectors and intervals: (1,2,3),(4,5),[6,7],(8,9],[10,11)

+

Alt vectors: ⟨1,2,3⟩,⟨4,5⟩,[6,7],(8,9],[10,11)

`}, "*"); }); cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded - cy.log('Look same in browser') + cy.log('Look same in browser (except alt-vector)') cy.get('#\\/_math1').find('.mjx-mrow').eq(0).invoke('text').then((text) => { expect(text.trim()).equal('(1,2,3),(4,5),[6,7],(8,9],[10,11)') }); @@ -642,6 +643,9 @@ describe('Math Tag Tests', function () { cy.get('#\\/_math4').find('.mjx-mrow').eq(0).invoke('text').then((text) => { expect(text.trim()).equal('(1,2,3),(4,5),[6,7],(8,9],[10,11)') }); + cy.get('#\\/_math5').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('⟨1,2,3⟩,⟨4,5⟩,[6,7],(8,9],[10,11)') + }); cy.log('Different internal values') cy.window().then(async (win) => { @@ -674,6 +678,13 @@ describe('Math Tag Tests', function () { ["interval", ["tuple", 8, 9], ["tuple", false, true]], ["interval", ["tuple", 10, 11], ["tuple", true, false]], ]); + expect(stateVariables['/_math5'].stateValues.value).eqls(["list", + ["altvector", 1, 2, 3], + ["altvector", 4, 5], + ["array", 6, 7], + ["interval", ["tuple", 8, 9], ["tuple", false, true]], + ["interval", ["tuple", 10, 11], ["tuple", true, false]], + ]); }); }) @@ -2317,6 +2328,19 @@ describe('Math Tag Tests', function () { cy.get("#\\/x4").should('contain.text', 'g'); check_values(["d", "e", "f", "g"], "list") + cy.log('change to 3D alt vector') + cy.get('#\\/m textarea').type("{ctrl+home}{shift+end}{backspace}\\langle a,b,c\\rangle {enter}", { force: true }) + cy.get("#\\/z").should('contain.text', 'c'); + + check_values(["a", "b", "c"], "altvector") + + cy.log('change xyz 3') + cy.get('#\\/mx_3 textarea').type('{end}{backspace}j{enter}', { force: true }) + cy.get('#\\/my_3 textarea').type('{end}{backspace}k{enter}', { force: true }) + cy.get('#\\/mz_3 textarea').type('{end}{backspace}l{enter}', { force: true }) + cy.get("#\\/z").should('contain.text', 'l'); + check_values(["j", "k", "l"], "altvector") + }); @@ -3285,27 +3309,49 @@ describe('Math Tag Tests', function () {

a

Tuple2: (a,b)

Vector2: (c,d)

+

Alt vector2: ⟨p,q⟩

Interval: (e,f)

Tuple3: (g,h,i)

Vector3: (j,k,l)

+

Alt vector3: ⟨r,s,t⟩

$tuple2+$tuple2

$tuple2+$tuple2

$vector2+$vector2

$vector2+$vector2

+

$altvector2+$altvector2

+

$altvector2+$altvector2

$interval+$interval

$interval+$interval

$tuple2+$vector2

$tuple2+$vector2

$vector2+$tuple2

$vector2+$tuple2

+

$tuple2+$altvector2

+

$tuple2+$altvector2

+

$altvector2+$tuple2

+

$altvector2+$tuple2

+

$vector2+$altvector2

+

$vector2+$altvector2

+

$altvector2+$vector2

+

$altvector2+$vector2

$tuple2-$vector2

$tuple2-$vector2

$vector2-$tuple2

$vector2-$tuple2

+

$tuple2-$altvector2

+

$tuple2-$altvector2

+

$altvector2-$tuple2

+

$altvector2-$tuple2

+

$vector2-$altvector2

+

$vector2-$altvector2

+

$altvector2-$vector2

+

$altvector2-$vector2

$tuple2+$interval

$tuple2+$interval

$vector2+$interval

$vector2+$interval

+

$altvector2+$interval

+

$altvector2+$interval

m$tuple2

m$tuple2

m$tuple2

@@ -3318,6 +3364,12 @@ describe('Math Tag Tests', function () {

$vector2 m

$vector2 m

$vector2 m

+

m$altvector2

+

m$altvector2

+

m$altvector2

+

$altvector2 m

+

$altvector2 m

+

$altvector2 m

m$interval

m$interval

m$interval

@@ -3327,19 +3379,43 @@ describe('Math Tag Tests', function () {

m$tuple2+$vector2*n

m$tuple2+$vector2*n

m$tuple2+$vector2*n

+

m$tuple2+$altvector2*n

+

m$tuple2+$altvector2*n

+

m$tuple2+$altvector2*n

+

m$vector2+$altvector2*n

+

m$vector2+$altvector2*n

+

m$vector2+$altvector2*n

$tuple3+$tuple3

$tuple3+$tuple3

$vector3+$vector3

$vector3+$vector3

+

$altvector3+$altvector3

+

$altvector3+$altvector3

$tuple3+$vector3

$tuple3+$vector3

$vector3+$tuple3

$vector3+$tuple3

+

$tuple3+$altvector3

+

$tuple3+$altvector3

+

$altvector3+$tuple3

+

$altvector3+$tuple3

+

$vector3+$altvector3

+

$vector3+$altvector3

+

$altvector3+$vector3

+

$altvector3+$vector3

$tuple3-$vector3

$tuple3-$vector3

$vector3-$tuple3

$vector3-$tuple3

+

$tuple3-$altvector3

+

$tuple3-$altvector3

+

$altvector3-$tuple3

+

$altvector3-$tuple3

+

$vector3-$altvector3

+

$vector3-$altvector3

+

$altvector3-$vector3

+

$altvector3-$vector3

m$tuple3

m$tuple3

m$tuple3

@@ -3352,9 +3428,21 @@ describe('Math Tag Tests', function () {

$vector3 m

$vector3 m

$vector3 m

+

m$altvector3

+

m$altvector3

+

m$altvector3

+

$altvector3 m

+

$altvector3 m

+

$altvector3 m

m$tuple3+$vector3*n

m$tuple3+$vector3*n

m$tuple3+$vector3*n

+

m$tuple3+$altvector3*n

+

m$tuple3+$altvector3*n

+

m$tuple3+$altvector3*n

+

m$vector3+$altvector3*n

+

m$vector3+$altvector3*n

+

m$vector3+$altvector3*n

`}, "*"); }); @@ -3364,20 +3452,40 @@ describe('Math Tag Tests', function () { cy.get('#\\/t2t2sumSimp .mjx-mrow').eq(0).should('have.text', '(2a,2b)'); cy.get('#\\/v2v2sum .mjx-mrow').eq(0).should('have.text', '(c,d)+(c,d)'); cy.get('#\\/v2v2sumSimp .mjx-mrow').eq(0).should('have.text', '(2c,2d)'); + cy.get('#\\/a2a2sum .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩+⟨p,q⟩'); + cy.get('#\\/a2a2sumSimp .mjx-mrow').eq(0).should('have.text', '⟨2p,2q⟩'); cy.get('#\\/iisum .mjx-mrow').eq(0).should('have.text', '(e,f)+(e,f)'); cy.get('#\\/iisumSimp .mjx-mrow').eq(0).should('have.text', '2(e,f)'); cy.get('#\\/t2v2sum .mjx-mrow').eq(0).should('have.text', '(a,b)+(c,d)'); cy.get('#\\/t2v2sumSimp .mjx-mrow').eq(0).should('have.text', '(a+c,b+d)'); cy.get('#\\/v2t2sum .mjx-mrow').eq(0).should('have.text', '(c,d)+(a,b)'); cy.get('#\\/v2t2sumSimp .mjx-mrow').eq(0).should('have.text', '(a+c,b+d)'); + cy.get('#\\/t2a2sum .mjx-mrow').eq(0).should('have.text', '(a,b)+⟨p,q⟩'); + cy.get('#\\/t2a2sumSimp .mjx-mrow').eq(0).should('have.text', '(a+p,b+q)'); + cy.get('#\\/a2t2sum .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩+(a,b)'); + cy.get('#\\/a2t2sumSimp .mjx-mrow').eq(0).should('have.text', '(a+p,b+q)'); + cy.get('#\\/v2a2sum .mjx-mrow').eq(0).should('have.text', '(c,d)+⟨p,q⟩'); + cy.get('#\\/v2a2sumSimp .mjx-mrow').eq(0).should('have.text', '(c+p,d+q)'); + cy.get('#\\/a2v2sum .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩+(c,d)'); + cy.get('#\\/a2v2sumSimp .mjx-mrow').eq(0).should('have.text', '(c+p,d+q)'); cy.get('#\\/t2v2diff .mjx-mrow').eq(0).should('have.text', '(a,b)−(c,d)'); cy.get('#\\/t2v2diffSimp .mjx-mrow').eq(0).should('have.text', '(a−c,b−d)'); cy.get('#\\/v2t2diff .mjx-mrow').eq(0).should('have.text', '(c,d)−(a,b)'); cy.get('#\\/v2t2diffSimp .mjx-mrow').eq(0).should('have.text', '(−a+c,−b+d)'); + cy.get('#\\/t2a2diff .mjx-mrow').eq(0).should('have.text', '(a,b)−⟨p,q⟩'); + cy.get('#\\/t2a2diffSimp .mjx-mrow').eq(0).should('have.text', '(a−p,b−q)'); + cy.get('#\\/a2t2diff .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩−(a,b)'); + cy.get('#\\/a2t2diffSimp .mjx-mrow').eq(0).should('have.text', '(−a+p,−b+q)'); + cy.get('#\\/v2a2diff .mjx-mrow').eq(0).should('have.text', '(c,d)−⟨p,q⟩'); + cy.get('#\\/v2a2diffSimp .mjx-mrow').eq(0).should('have.text', '(c−p,d−q)'); + cy.get('#\\/a2v2diff .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩−(c,d)'); + cy.get('#\\/a2v2diffSimp .mjx-mrow').eq(0).should('have.text', '(−c+p,−d+q)'); cy.get('#\\/t2isum .mjx-mrow').eq(0).should('have.text', '(a,b)+(e,f)'); cy.get('#\\/t2isumSimp .mjx-mrow').eq(0).should('have.text', '(e,f)+(a,b)'); cy.get('#\\/v2isum .mjx-mrow').eq(0).should('have.text', '(c,d)+(e,f)'); cy.get('#\\/v2isumSimp .mjx-mrow').eq(0).should('have.text', '(e,f)+(c,d)'); + cy.get('#\\/a2isum .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩+(e,f)'); + cy.get('#\\/a2isumSimp .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩+(e,f)'); cy.get('#\\/st2mul .mjx-mrow').eq(0).should('have.text', 'm(a,b)'); cy.get('#\\/st2mulSimp .mjx-mrow').eq(0).should('have.text', '(am,bm)'); cy.get('#\\/st2mulExp .mjx-mrow').eq(0).should('have.text', '(am,bm)'); @@ -3390,6 +3498,12 @@ describe('Math Tag Tests', function () { cy.get('#\\/v2smul .mjx-mrow').eq(0).should('have.text', '(c,d)m'); cy.get('#\\/v2smulSimp .mjx-mrow').eq(0).should('have.text', '(cm,dm)'); cy.get('#\\/v2smulExp .mjx-mrow').eq(0).should('have.text', '(cm,dm)'); + cy.get('#\\/sa2mul .mjx-mrow').eq(0).should('have.text', 'm⟨p,q⟩'); + cy.get('#\\/sa2mulSimp .mjx-mrow').eq(0).should('have.text', '⟨mp,mq⟩'); + cy.get('#\\/sa2mulExp .mjx-mrow').eq(0).should('have.text', '⟨mp,mq⟩'); + cy.get('#\\/a2smul .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩m'); + cy.get('#\\/a2smulSimp .mjx-mrow').eq(0).should('have.text', '⟨mp,mq⟩'); + cy.get('#\\/a2smulExp .mjx-mrow').eq(0).should('have.text', '⟨mp,mq⟩'); cy.get('#\\/simul .mjx-mrow').eq(0).should('have.text', 'm(e,f)'); cy.get('#\\/simulSimp .mjx-mrow').eq(0).should('have.text', 'm(e,f)'); cy.get('#\\/simulExp .mjx-mrow').eq(0).should('have.text', 'm(e,f)'); @@ -3399,19 +3513,43 @@ describe('Math Tag Tests', function () { cy.get('#\\/st2v2ssum .mjx-mrow').eq(0).should('have.text', 'm(a,b)+(c,d)n'); cy.get('#\\/st2v2ssumSimp .mjx-mrow').eq(0).should('have.text', '(am+cn,bm+dn)'); cy.get('#\\/st2v2ssumExp .mjx-mrow').eq(0).should('have.text', '(am+cn,bm+dn)'); + cy.get('#\\/st2a2ssum .mjx-mrow').eq(0).should('have.text', 'm(a,b)+⟨p,q⟩n'); + cy.get('#\\/st2a2ssumSimp .mjx-mrow').eq(0).should('have.text', '(am+np,bm+nq)'); + cy.get('#\\/st2a2ssumExp .mjx-mrow').eq(0).should('have.text', '(am+np,bm+nq)'); + cy.get('#\\/sv2a2ssum .mjx-mrow').eq(0).should('have.text', 'm(c,d)+⟨p,q⟩n'); + cy.get('#\\/sv2a2ssumSimp .mjx-mrow').eq(0).should('have.text', '(cm+np,dm+nq)'); + cy.get('#\\/sv2a2ssumExp .mjx-mrow').eq(0).should('have.text', '(cm+np,dm+nq)'); cy.get('#\\/t3t3sum .mjx-mrow').eq(0).should('have.text', '(g,h,i)+(g,h,i)'); cy.get('#\\/t3t3sumSimp .mjx-mrow').eq(0).should('have.text', '(2g,2h,2i)'); cy.get('#\\/v3v3sum .mjx-mrow').eq(0).should('have.text', '(j,k,l)+(j,k,l)'); cy.get('#\\/v3v3sumSimp .mjx-mrow').eq(0).should('have.text', '(2j,2k,2l)'); + cy.get('#\\/a3a3sum .mjx-mrow').eq(0).should('have.text', '⟨r,s,t⟩+⟨r,s,t⟩'); + cy.get('#\\/a3a3sumSimp .mjx-mrow').eq(0).should('have.text', '⟨2r,2s,2t⟩'); cy.get('#\\/t3v3sum .mjx-mrow').eq(0).should('have.text', '(g,h,i)+(j,k,l)'); cy.get('#\\/t3v3sumSimp .mjx-mrow').eq(0).should('have.text', '(g+j,h+k,i+l)'); cy.get('#\\/v3t3sum .mjx-mrow').eq(0).should('have.text', '(j,k,l)+(g,h,i)'); cy.get('#\\/v3t3sumSimp .mjx-mrow').eq(0).should('have.text', '(g+j,h+k,i+l)'); + cy.get('#\\/t3a3sum .mjx-mrow').eq(0).should('have.text', '(g,h,i)+⟨r,s,t⟩'); + cy.get('#\\/t3a3sumSimp .mjx-mrow').eq(0).should('have.text', '(g+r,h+s,i+t)'); + cy.get('#\\/a3t3sum .mjx-mrow').eq(0).should('have.text', '⟨r,s,t⟩+(g,h,i)'); + cy.get('#\\/a3t3sumSimp .mjx-mrow').eq(0).should('have.text', '(g+r,h+s,i+t)'); + cy.get('#\\/v3a3sum .mjx-mrow').eq(0).should('have.text', '(j,k,l)+⟨r,s,t⟩'); + cy.get('#\\/v3a3sumSimp .mjx-mrow').eq(0).should('have.text', '(j+r,k+s,l+t)'); + cy.get('#\\/a3v3sum .mjx-mrow').eq(0).should('have.text', '⟨r,s,t⟩+(j,k,l)'); + cy.get('#\\/a3v3sumSimp .mjx-mrow').eq(0).should('have.text', '(j+r,k+s,l+t)'); cy.get('#\\/t3v3diff .mjx-mrow').eq(0).should('have.text', '(g,h,i)−(j,k,l)'); cy.get('#\\/t3v3diffSimp .mjx-mrow').eq(0).should('have.text', '(g−j,h−k,i−l)'); cy.get('#\\/v3t3diff .mjx-mrow').eq(0).should('have.text', '(j,k,l)−(g,h,i)'); cy.get('#\\/v3t3diffSimp .mjx-mrow').eq(0).should('have.text', '(−g+j,−h+k,−i+l)'); + cy.get('#\\/t3a3diff .mjx-mrow').eq(0).should('have.text', '(g,h,i)−⟨r,s,t⟩'); + cy.get('#\\/t3a3diffSimp .mjx-mrow').eq(0).should('have.text', '(g−r,h−s,i−t)'); + cy.get('#\\/a3t3diff .mjx-mrow').eq(0).should('have.text', '⟨r,s,t⟩−(g,h,i)'); + cy.get('#\\/a3t3diffSimp .mjx-mrow').eq(0).should('have.text', '(−g+r,−h+s,−i+t)'); + cy.get('#\\/v3a3diff .mjx-mrow').eq(0).should('have.text', '(j,k,l)−⟨r,s,t⟩'); + cy.get('#\\/v3a3diffSimp .mjx-mrow').eq(0).should('have.text', '(j−r,k−s,l−t)'); + cy.get('#\\/a3v3diff .mjx-mrow').eq(0).should('have.text', '⟨r,s,t⟩−(j,k,l)'); + cy.get('#\\/a3v3diffSimp .mjx-mrow').eq(0).should('have.text', '(−j+r,−k+s,−l+t)'); cy.get('#\\/st3mul .mjx-mrow').eq(0).should('have.text', 'm(g,h,i)'); cy.get('#\\/st3mulSimp .mjx-mrow').eq(0).should('have.text', '(gm,hm,im)'); cy.get('#\\/st3mulExp .mjx-mrow').eq(0).should('have.text', '(gm,hm,im)'); @@ -3424,9 +3562,21 @@ describe('Math Tag Tests', function () { cy.get('#\\/v3smul .mjx-mrow').eq(0).should('have.text', '(j,k,l)m'); cy.get('#\\/v3smulSimp .mjx-mrow').eq(0).should('have.text', '(jm,km,lm)'); cy.get('#\\/v3smulExp .mjx-mrow').eq(0).should('have.text', '(jm,km,lm)'); + cy.get('#\\/sa3mul .mjx-mrow').eq(0).should('have.text', 'm⟨r,s,t⟩'); + cy.get('#\\/sa3mulSimp .mjx-mrow').eq(0).should('have.text', '⟨mr,ms,mt⟩'); + cy.get('#\\/sa3mulExp .mjx-mrow').eq(0).should('have.text', '⟨mr,ms,mt⟩'); + cy.get('#\\/a3smul .mjx-mrow').eq(0).should('have.text', '⟨r,s,t⟩m'); + cy.get('#\\/a3smulSimp .mjx-mrow').eq(0).should('have.text', '⟨mr,ms,mt⟩'); + cy.get('#\\/a3smulExp .mjx-mrow').eq(0).should('have.text', '⟨mr,ms,mt⟩'); cy.get('#\\/st3v3ssum .mjx-mrow').eq(0).should('have.text', 'm(g,h,i)+(j,k,l)n'); cy.get('#\\/st3v3ssumSimp .mjx-mrow').eq(0).should('have.text', '(gm+jn,hm+kn,im+ln)'); cy.get('#\\/st3v3ssumExp .mjx-mrow').eq(0).should('have.text', '(gm+jn,hm+kn,im+ln)'); + cy.get('#\\/st3a3ssum .mjx-mrow').eq(0).should('have.text', 'm(g,h,i)+⟨r,s,t⟩n'); + cy.get('#\\/st3a3ssumSimp .mjx-mrow').eq(0).should('have.text', '(gm+nr,hm+ns,im+nt)'); + cy.get('#\\/st3a3ssumExp .mjx-mrow').eq(0).should('have.text', '(gm+nr,hm+ns,im+nt)'); + cy.get('#\\/sv3a3ssum .mjx-mrow').eq(0).should('have.text', 'm(j,k,l)+⟨r,s,t⟩n'); + cy.get('#\\/sv3a3ssumSimp .mjx-mrow').eq(0).should('have.text', '(jm+nr,km+ns,lm+nt)'); + cy.get('#\\/sv3a3ssumExp .mjx-mrow').eq(0).should('have.text', '(jm+nr,km+ns,lm+nt)'); }); @@ -3600,6 +3750,47 @@ describe('Math Tag Tests', function () { }); + it('matrix-vector multiplication', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` +

a

+

matrix22: \\begin{bmatrix}a&b\\\\c&d\\end{bmatrix}

+

tuple2: (e,f)

+

vector2: (g,h)

+

alt vector2: ⟨p,q⟩

+

$matrix22$tuple2

+

$matrix22$tuple2

+

$tuple2$matrix22

+

$tuple2$matrix22

+

$matrix22$vector2

+

$matrix22$vector2

+

$vector2$matrix22

+

$vector2$matrix22

+

$matrix22$altvector2

+

$matrix22$altvector2

+

$altvector2$matrix22

+

$altvector2$matrix22

+ `}, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get('#\\/m22t2 .mjx-mrow').eq(0).should('have.text', '[abcd](e,f)'); + cy.get('#\\/m22t2Exp .mjx-mrow').eq(0).should('have.text', '(ae+bf,ce+df)'); + cy.get('#\\/t2m22 .mjx-mrow').eq(0).should('have.text', '(e,f)[abcd]'); + cy.get('#\\/t2m22Exp .mjx-mrow').eq(0).should('have.text', '(e,f)[abcd]'); + cy.get('#\\/m22v2 .mjx-mrow').eq(0).should('have.text', '[abcd](g,h)'); + cy.get('#\\/m22v2Exp .mjx-mrow').eq(0).should('have.text', '(ag+bh,cg+dh)'); + cy.get('#\\/v2m22 .mjx-mrow').eq(0).should('have.text', '(g,h)[abcd]'); + cy.get('#\\/v2m22Exp .mjx-mrow').eq(0).should('have.text', '(g,h)[abcd]'); + cy.get('#\\/m22a2 .mjx-mrow').eq(0).should('have.text', '[abcd]⟨p,q⟩'); + cy.get('#\\/m22a2Exp .mjx-mrow').eq(0).should('have.text', '⟨ap+bq,cp+dq⟩'); + cy.get('#\\/a2m22 .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩[abcd]'); + cy.get('#\\/a2m22Exp .mjx-mrow').eq(0).should('have.text', '⟨p,q⟩[abcd]'); + + }); + it('matrix and vector state variables', () => { cy.window().then(async (win) => { win.postMessage({ @@ -3622,6 +3813,9 @@ describe('Math Tag Tests', function () { (1,2) (1,2)' (1,2)^T + ⟨1,2⟩ + ⟨1,2⟩' + ⟨1,2⟩^T

N dimensions: @@ -3633,6 +3827,9 @@ describe('Math Tag Tests', function () { + + +

Vectors: @@ -3644,6 +3841,9 @@ describe('Math Tag Tests', function () { + + +

Vectors as math: @@ -3655,6 +3855,9 @@ describe('Math Tag Tests', function () { + + +

Vector x components: @@ -3666,6 +3869,9 @@ describe('Math Tag Tests', function () { + + +

Vector y components: @@ -3677,6 +3883,9 @@ describe('Math Tag Tests', function () { + + +

Vector x components b: @@ -3688,6 +3897,9 @@ describe('Math Tag Tests', function () { + + +

Vector y components b: @@ -3699,6 +3911,9 @@ describe('Math Tag Tests', function () { + + +

Matrix size: @@ -3710,6 +3925,9 @@ describe('Math Tag Tests', function () { + + +

N rows: @@ -3721,6 +3939,9 @@ describe('Math Tag Tests', function () { + + +

N columns: @@ -3732,6 +3953,9 @@ describe('Math Tag Tests', function () { + + +

Matrices: @@ -3743,6 +3967,9 @@ describe('Math Tag Tests', function () { + + +

Matrices as math: @@ -3754,6 +3981,9 @@ describe('Math Tag Tests', function () { + + +

Row 1: @@ -3765,6 +3995,9 @@ describe('Math Tag Tests', function () { + + +

Row 1 b: @@ -3776,6 +4009,9 @@ describe('Math Tag Tests', function () { + + +

Row 1 c: @@ -3787,6 +4023,9 @@ describe('Math Tag Tests', function () { + + +

Row 2: @@ -3798,6 +4037,9 @@ describe('Math Tag Tests', function () { + + +

Row 2 b: @@ -3809,6 +4051,9 @@ describe('Math Tag Tests', function () { + + +

Row 2 c: @@ -3820,6 +4065,9 @@ describe('Math Tag Tests', function () { + + +

Column 1: @@ -3831,6 +4079,9 @@ describe('Math Tag Tests', function () { + + +

Column 1 b: @@ -3842,6 +4093,9 @@ describe('Math Tag Tests', function () { + + +

Column 2: @@ -3853,6 +4107,9 @@ describe('Math Tag Tests', function () { + + +

Column 2 b: @@ -3864,6 +4121,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 12: @@ -3876,6 +4136,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 12 b: @@ -3887,6 +4150,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 12 c: @@ -3898,6 +4164,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 12 d: @@ -3909,6 +4178,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 12 e: @@ -3920,6 +4192,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 12 f: @@ -3931,6 +4206,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 21: @@ -3942,6 +4220,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 21 b: @@ -3953,6 +4234,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 21 c: @@ -3964,6 +4248,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 21 d: @@ -3975,6 +4262,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 21 e: @@ -3986,6 +4276,9 @@ describe('Math Tag Tests', function () { + + +

Matrix entry 21 f: @@ -3997,6 +4290,9 @@ describe('Math Tag Tests', function () { + + +

Graph vectors

@@ -4010,6 +4306,9 @@ describe('Math Tag Tests', function () { + + +

Change matrices

@@ -4022,6 +4321,9 @@ describe('Math Tag Tests', function () {

+

+

+

`}, "*"); }); @@ -4037,6 +4339,9 @@ describe('Math Tag Tests', function () { cy.get('#\\/v7 .mjx-mrow').eq(0).should('have.text', "(1,2)"); cy.get('#\\/v8 .mjx-mrow').eq(0).should('have.text', "(1,2)′"); cy.get('#\\/v9 .mjx-mrow').eq(0).should('have.text', "(1,2)T"); + cy.get('#\\/v10 .mjx-mrow').eq(0).should('have.text', "⟨1,2⟩"); + cy.get('#\\/v11 .mjx-mrow').eq(0).should('have.text', "⟨1,2⟩′"); + cy.get('#\\/v12 .mjx-mrow').eq(0).should('have.text', "⟨1,2⟩T"); cy.get("#\\/v1nd").should('have.text', '2') cy.get("#\\/v2nd").should('have.text', '2') @@ -4047,6 +4352,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7nd").should('have.text', '2') cy.get("#\\/v8nd").should('have.text', '2') cy.get("#\\/v9nd").should('have.text', '2') + cy.get("#\\/v10nd").should('have.text', '2') + cy.get("#\\/v11nd").should('have.text', '2') + cy.get("#\\/v12nd").should('have.text', '2') cy.get("#\\/v1v .mjx-mrow").eq(0).should('have.text', '(1,2)') cy.get("#\\/v2v .mjx-mrow").eq(0).should('have.text', '(1,2)') @@ -4057,6 +4365,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7v .mjx-mrow").eq(0).should('have.text', '(1,2)') cy.get("#\\/v8v .mjx-mrow").eq(0).should('have.text', '(1,2)') cy.get("#\\/v9v .mjx-mrow").eq(0).should('have.text', '(1,2)') + cy.get("#\\/v10v .mjx-mrow").eq(0).should('have.text', '(1,2)') + cy.get("#\\/v11v .mjx-mrow").eq(0).should('have.text', '(1,2)') + cy.get("#\\/v12v .mjx-mrow").eq(0).should('have.text', '(1,2)') cy.get("#\\/v1vm .mjx-mrow").eq(0).should('have.text', '(1,2)') cy.get("#\\/v2vm .mjx-mrow").eq(0).should('have.text', '(1,2)') @@ -4067,6 +4378,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7vm .mjx-mrow").eq(0).should('have.text', '(1,2)') cy.get("#\\/v8vm .mjx-mrow").eq(0).should('have.text', '(1,2)') cy.get("#\\/v9vm .mjx-mrow").eq(0).should('have.text', '(1,2)') + cy.get("#\\/v10vm .mjx-mrow").eq(0).should('have.text', '(1,2)') + cy.get("#\\/v11vm .mjx-mrow").eq(0).should('have.text', '(1,2)') + cy.get("#\\/v12vm .mjx-mrow").eq(0).should('have.text', '(1,2)') cy.get("#\\/v1x .mjx-mrow").eq(0).should('have.text', '1') cy.get("#\\/v2x .mjx-mrow").eq(0).should('have.text', '1') @@ -4077,6 +4391,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7x .mjx-mrow").eq(0).should('have.text', '1') cy.get("#\\/v8x .mjx-mrow").eq(0).should('have.text', '1') cy.get("#\\/v9x .mjx-mrow").eq(0).should('have.text', '1') + cy.get("#\\/v10x .mjx-mrow").eq(0).should('have.text', '1') + cy.get("#\\/v11x .mjx-mrow").eq(0).should('have.text', '1') + cy.get("#\\/v12x .mjx-mrow").eq(0).should('have.text', '1') cy.get("#\\/v1xb .mjx-mrow").eq(0).should('have.text', '1') cy.get("#\\/v2xb .mjx-mrow").eq(0).should('have.text', '1') @@ -4087,6 +4404,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7xb .mjx-mrow").eq(0).should('have.text', '1') cy.get("#\\/v8xb .mjx-mrow").eq(0).should('have.text', '1') cy.get("#\\/v9xb .mjx-mrow").eq(0).should('have.text', '1') + cy.get("#\\/v10xb .mjx-mrow").eq(0).should('have.text', '1') + cy.get("#\\/v11xb .mjx-mrow").eq(0).should('have.text', '1') + cy.get("#\\/v12xb .mjx-mrow").eq(0).should('have.text', '1') cy.get("#\\/v1y .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v2y .mjx-mrow").eq(0).should('have.text', '2') @@ -4097,6 +4417,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7y .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v8y .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v9y .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v10y .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v11y .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v12y .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v1yb .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v2yb .mjx-mrow").eq(0).should('have.text', '2') @@ -4107,6 +4430,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7yb .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v8yb .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v9yb .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v10yb .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v11yb .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v12yb .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v1ms").should('have.text', '2, 1') cy.get("#\\/v2ms").should('have.text', '1, 2') @@ -4117,6 +4443,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7ms").should('have.text', '2, 1') cy.get("#\\/v8ms").should('have.text', '1, 2') cy.get("#\\/v9ms").should('have.text', '1, 2') + cy.get("#\\/v10ms").should('have.text', '2, 1') + cy.get("#\\/v11ms").should('have.text', '1, 2') + cy.get("#\\/v12ms").should('have.text', '1, 2') cy.get("#\\/v1nr").should('have.text', '2') cy.get("#\\/v2nr").should('have.text', '1') @@ -4127,6 +4456,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7nr").should('have.text', '2') cy.get("#\\/v8nr").should('have.text', '1') cy.get("#\\/v9nr").should('have.text', '1') + cy.get("#\\/v10nr").should('have.text', '2') + cy.get("#\\/v11nr").should('have.text', '1') + cy.get("#\\/v12nr").should('have.text', '1') cy.get("#\\/v1nc").should('have.text', '1') cy.get("#\\/v2nc").should('have.text', '2') @@ -4137,6 +4469,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7nc").should('have.text', '1') cy.get("#\\/v8nc").should('have.text', '2') cy.get("#\\/v9nc").should('have.text', '2') + cy.get("#\\/v10nc").should('have.text', '1') + cy.get("#\\/v11nc").should('have.text', '2') + cy.get("#\\/v12nc").should('have.text', '2') cy.get("#\\/v1m .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v2m .mjx-mrow").eq(0).should('have.text', '[12]') @@ -4147,6 +4482,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7m .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v8m .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v9m .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v10m .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v11m .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v12m .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v1mm .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v2mm .mjx-mrow").eq(0).should('have.text', '[12]') @@ -4157,6 +4495,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7mm .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v8mm .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v9mm .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v10mm .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v11mm .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v12mm .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v1r1 .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v2r1 .mjx-mrow").eq(0).should('have.text', '[12]') @@ -4167,6 +4508,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7r1 .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v8r1 .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v9r1 .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v10r1 .mjx-mrow").eq(0).should('have.text', '[1]') + cy.get("#\\/v11r1 .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v12r1 .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v1r1b .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v2r1b .mjx-mrow").eq(0).should('have.text', '[12]') @@ -4177,6 +4521,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7r1b .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v8r1b .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v9r1b .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v10r1b .mjx-mrow").eq(0).should('have.text', '[1]') + cy.get("#\\/v11r1b .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v12r1b .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v1r1c .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v2r1c .mjx-mrow").eq(0).should('have.text', '[12]') @@ -4187,6 +4534,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7r1c .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v8r1c .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v9r1c .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v10r1c .mjx-mrow").eq(0).should('have.text', '[1]') + cy.get("#\\/v11r1c .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v12r1c .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v1r2 .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v2r2 .mjx-mrow").eq(0).should('have.text', '[]') @@ -4197,6 +4547,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7r2 .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v8r2 .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v9r2 .mjx-mrow").eq(0).should('have.text', '[]') + cy.get("#\\/v10r2 .mjx-mrow").eq(0).should('have.text', '[2]') + cy.get("#\\/v11r2 .mjx-mrow").eq(0).should('have.text', '[]') + cy.get("#\\/v12r2 .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v1r2b .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v2r2b .mjx-mrow").eq(0).should('have.text', '[]') @@ -4207,6 +4560,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7r2b .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v8r2b .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v9r2b .mjx-mrow").eq(0).should('have.text', '[]') + cy.get("#\\/v10r2b .mjx-mrow").eq(0).should('have.text', '[2]') + cy.get("#\\/v11r2b .mjx-mrow").eq(0).should('have.text', '[]') + cy.get("#\\/v12r2b .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v1r2c .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v2r2c .mjx-mrow").eq(0).should('have.text', '[]') @@ -4217,6 +4573,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7r2c .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v8r2c .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v9r2c .mjx-mrow").eq(0).should('have.text', '[]') + cy.get("#\\/v10r2c .mjx-mrow").eq(0).should('have.text', '[2]') + cy.get("#\\/v11r2c .mjx-mrow").eq(0).should('have.text', '[]') + cy.get("#\\/v12r2c .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v1c1 .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v2c1 .mjx-mrow").eq(0).should('have.text', '[1]') @@ -4227,6 +4586,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7c1 .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v8c1 .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v9c1 .mjx-mrow").eq(0).should('have.text', '[1]') + cy.get("#\\/v10c1 .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v11c1 .mjx-mrow").eq(0).should('have.text', '[1]') + cy.get("#\\/v12c1 .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v1c1b .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v2c1b .mjx-mrow").eq(0).should('have.text', '[1]') @@ -4237,6 +4599,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7c1b .mjx-mrow").eq(0).should('have.text', '[12]') cy.get("#\\/v8c1b .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v9c1b .mjx-mrow").eq(0).should('have.text', '[1]') + cy.get("#\\/v10c1b .mjx-mrow").eq(0).should('have.text', '[12]') + cy.get("#\\/v11c1b .mjx-mrow").eq(0).should('have.text', '[1]') + cy.get("#\\/v12c1b .mjx-mrow").eq(0).should('have.text', '[1]') cy.get("#\\/v1c2 .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v2c2 .mjx-mrow").eq(0).should('have.text', '[2]') @@ -4247,6 +4612,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7c2 .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v8c2 .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v9c2 .mjx-mrow").eq(0).should('have.text', '[2]') + cy.get("#\\/v10c2 .mjx-mrow").eq(0).should('have.text', '[]') + cy.get("#\\/v11c2 .mjx-mrow").eq(0).should('have.text', '[2]') + cy.get("#\\/v12c2 .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v1c2b .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v2c2b .mjx-mrow").eq(0).should('have.text', '[2]') @@ -4257,6 +4625,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7c2b .mjx-mrow").eq(0).should('have.text', '[]') cy.get("#\\/v8c2b .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v9c2b .mjx-mrow").eq(0).should('have.text', '[2]') + cy.get("#\\/v10c2b .mjx-mrow").eq(0).should('have.text', '[]') + cy.get("#\\/v11c2b .mjx-mrow").eq(0).should('have.text', '[2]') + cy.get("#\\/v12c2b .mjx-mrow").eq(0).should('have.text', '[2]') cy.get("#\\/v1me12 .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v2me12 .mjx-mrow").eq(0).should('have.text', '2') @@ -4267,6 +4638,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me12 .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v8me12 .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v9me12 .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v10me12 .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v11me12 .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v12me12 .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v1me12b .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v2me12b .mjx-mrow").eq(0).should('have.text', '2') @@ -4277,6 +4651,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me12b .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v8me12b .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v9me12b .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v10me12b .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v11me12b .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v12me12b .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v1me12c .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v2me12c .mjx-mrow").eq(0).should('have.text', '2') @@ -4287,6 +4664,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me12c .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v8me12c .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v9me12c .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v10me12c .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v11me12c .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v12me12c .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v1me12d .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v2me12d .mjx-mrow").eq(0).should('have.text', '2') @@ -4297,6 +4677,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me12d .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v8me12d .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v9me12d .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v10me12d .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v11me12d .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v12me12d .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v1me12e .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v2me12e .mjx-mrow").eq(0).should('have.text', '2') @@ -4307,6 +4690,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me12e .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v8me12e .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v9me12e .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v10me12e .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v11me12e .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v12me12e .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v1me12f .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v2me12f .mjx-mrow").eq(0).should('have.text', '2') @@ -4317,6 +4703,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me12f .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v8me12f .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v9me12f .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v10me12f .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v11me12f .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v12me12f .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v1me21 .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v2me21 .mjx-mrow").eq(0).should('have.text', '\uff3f') @@ -4327,6 +4716,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me21 .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v8me21 .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v9me21 .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v10me21 .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v11me21 .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v12me21 .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v1me21b .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v2me21b .mjx-mrow").eq(0).should('have.text', '\uff3f') @@ -4337,6 +4729,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me21b .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v8me21b .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v9me21b .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v10me21b .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v11me21b .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v12me21b .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v1me21c .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v2me21c .mjx-mrow").eq(0).should('have.text', '\uff3f') @@ -4347,6 +4742,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me21c .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v8me21c .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v9me21c .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v10me21c .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v11me21c .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v12me21c .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v1me21d .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v2me21d .mjx-mrow").eq(0).should('have.text', '\uff3f') @@ -4357,6 +4755,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me21d .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v8me21d .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v9me21d .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v10me21d .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v11me21d .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v12me21d .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v1me21e .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v2me21e .mjx-mrow").eq(0).should('have.text', '\uff3f') @@ -4367,6 +4768,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me21e .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v8me21e .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v9me21e .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v10me21e .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v11me21e .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v12me21e .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v1me21f .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v2me21f .mjx-mrow").eq(0).should('have.text', '\uff3f') @@ -4377,6 +4781,9 @@ describe('Math Tag Tests', function () { cy.get("#\\/v7me21f .mjx-mrow").eq(0).should('have.text', '2') cy.get("#\\/v8me21f .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.get("#\\/v9me21f .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v10me21f .mjx-mrow").eq(0).should('have.text', '2') + cy.get("#\\/v11me21f .mjx-mrow").eq(0).should('have.text', '\uff3f') + cy.get("#\\/v12me21f .mjx-mrow").eq(0).should('have.text', '\uff3f') cy.log('move vectors') @@ -4446,10 +4853,31 @@ describe('Math Tag Tests', function () { headcoords: [2, 9] } }) + win.callAction1({ + actionName: "moveVector", + componentName: "/v10vb", + args: { + headcoords: [2, 10] + } + }) + win.callAction1({ + actionName: "moveVector", + componentName: "/v11vb", + args: { + headcoords: [2, 11] + } + }) + win.callAction1({ + actionName: "moveVector", + componentName: "/v12vb", + args: { + headcoords: [2, 12] + } + }) }) - cy.get('#\\/v9 .mjx-mrow').should('contain.text', "(2,9)T"); + cy.get('#\\/v12 .mjx-mrow').should('contain.text', "⟨2,12⟩T"); cy.get('#\\/v1 .mjx-mrow').eq(0).should('have.text', "[21]"); cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', "[22]"); @@ -4460,6 +4888,9 @@ describe('Math Tag Tests', function () { cy.get('#\\/v7 .mjx-mrow').eq(0).should('have.text', "(2,7)"); cy.get('#\\/v8 .mjx-mrow').eq(0).should('have.text', "(2,8)′"); cy.get('#\\/v9 .mjx-mrow').eq(0).should('have.text', "(2,9)T"); + cy.get('#\\/v10 .mjx-mrow').eq(0).should('have.text', "⟨2,10⟩"); + cy.get('#\\/v11 .mjx-mrow').eq(0).should('have.text', "⟨2,11⟩′"); + cy.get('#\\/v12 .mjx-mrow').eq(0).should('have.text', "⟨2,12⟩T"); cy.log('change from matrix inputs') @@ -4482,9 +4913,15 @@ describe('Math Tag Tests', function () { cy.get('#\\/mi8_component_0_1 textarea').type("{end}{backspace}-8{enter}", { force: true }) cy.get('#\\/mi9_component_0_0 textarea').type("{end}{backspace}3{enter}", { force: true }) cy.get('#\\/mi9_component_0_1 textarea').type("{end}{backspace}-9{enter}", { force: true }) + cy.get('#\\/mi10_component_0_0 textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/mi10_component_1_0 textarea').type("{end}{backspace}{backspace}-10{enter}", { force: true }) + cy.get('#\\/mi11_component_0_0 textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/mi11_component_0_1 textarea').type("{end}{backspace}{backspace}-11{enter}", { force: true }) + cy.get('#\\/mi12_component_0_0 textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/mi12_component_0_1 textarea').type("{end}{backspace}{backspace}-12{enter}", { force: true }) - cy.get('#\\/v9 .mjx-mrow').should('contain.text', "(3,−9)T"); + cy.get('#\\/v12 .mjx-mrow').should('contain.text', "⟨3,−12⟩T"); cy.get('#\\/v1 .mjx-mrow').eq(0).should('have.text', "[3−1]"); cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', "[3−2]"); @@ -4495,6 +4932,9 @@ describe('Math Tag Tests', function () { cy.get('#\\/v7 .mjx-mrow').eq(0).should('have.text', "(3,−7)"); cy.get('#\\/v8 .mjx-mrow').eq(0).should('have.text', "(3,−8)′"); cy.get('#\\/v9 .mjx-mrow').eq(0).should('have.text', "(3,−9)T"); + cy.get('#\\/v10 .mjx-mrow').eq(0).should('have.text', "⟨3,−10⟩"); + cy.get('#\\/v11 .mjx-mrow').eq(0).should('have.text', "⟨3,−11⟩′"); + cy.get('#\\/v12 .mjx-mrow').eq(0).should('have.text', "⟨3,−12⟩T"); }); @@ -4785,7 +5225,7 @@ describe('Math Tag Tests', function () { cy.get("#\\/m1r2c .mjx-mrow").eq(0).should('have.text', '[34]') cy.get("#\\/m2r2c .mjx-mrow").eq(0).should('have.text', '[34]') cy.get("#\\/m3r2c .mjx-mrow").eq(0).should('have.text', '[34]') - + cy.get("#\\/m1r3 .mjx-mrow").eq(0).should('have.text', '[56]') cy.get("#\\/m2r3 .mjx-mrow").eq(0).should('have.text', '[56]') cy.get("#\\/m3r3 .mjx-mrow").eq(0).should('have.text', '[56]') @@ -5243,8 +5683,8 @@ describe('Math Tag Tests', function () { cy.log("change content of math") - cy.get('#\\/content1 textarea').type("{end}+5{enter}", {force: true}) - cy.get('#\\/content2 textarea').type("{end}-a{enter}", {force: true}) + cy.get('#\\/content1 textarea').type("{end}+5{enter}", { force: true }) + cy.get('#\\/content2 textarea').type("{end}-a{enter}", { force: true }) cy.get("#\\/pContent2 .mjx-mrow").should('contain.text', 'e−x2−a') diff --git a/cypress/e2e/DoenetML/tagSpecific/matrixinput.cy.js b/cypress/e2e/DoenetML/tagSpecific/matrixinput.cy.js index e40f46402b..84a7cbd429 100644 --- a/cypress/e2e/DoenetML/tagSpecific/matrixinput.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/matrixinput.cy.js @@ -1531,15 +1531,13 @@ describe('MatrixInput Tag Tests', function () { }) - it('prefill with vector, start smaller', () => { + it('prefill with altvector', () => { cy.window().then(async (win) => { win.postMessage({ doenetML: ` a -

Number of rows:

-

Number of columns:

-

Matrix 1:

+

Matrix 1:

Matrix 2:

`}, "*"); }); @@ -1547,34 +1545,26 @@ describe('MatrixInput Tag Tests', function () { cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ab]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 0, 0], ["tuple"]] + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'a'], ["tuple", 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('add row and column') - cy.get('#\\/mi1_columnIncrement').click(); - cy.get('#\\/mi1_rowIncrement').click(); + cy.log('remove row') + cy.get('#\\/mi1_rowDecrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[a]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') }) @@ -1583,22 +1573,15 @@ describe('MatrixInput Tag Tests', function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'a']]] - console.log(stateVariables['/mi1'].stateValues.value) expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); cy.log('change value') - cy.get('#\\/mi1 textarea').type("{end}{backspace}e{enter}", { force: true }); + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1611,17 +1594,11 @@ describe('MatrixInput Tag Tests', function () { expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('add row') + cy.log('restore row') cy.get('#\\/mi1_rowIncrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1637,17 +1614,12 @@ describe('MatrixInput Tag Tests', function () { expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); + cy.log('type f in second row') cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1663,17 +1635,11 @@ describe('MatrixInput Tag Tests', function () { expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('add column via mathinput') - cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + cy.log('add column') + cy.get('#\\/mi1_columnIncrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1701,12 +1667,6 @@ describe('MatrixInput Tag Tests', function () { cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1729,17 +1689,11 @@ describe('MatrixInput Tag Tests', function () { }); - cy.log('add row via mathinput') - cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1774,12 +1728,6 @@ describe('MatrixInput Tag Tests', function () { cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1809,17 +1757,13 @@ describe('MatrixInput Tag Tests', function () { cy.log('down to one entry') - cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) - cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/mi1_rowDecrement').click(); + cy.get('#\\/mi1_columnDecrement').click(); + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + cy.get('#\\/mi1_rowDecrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1839,12 +1783,6 @@ describe('MatrixInput Tag Tests', function () { cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') }) @@ -1861,17 +1799,16 @@ describe('MatrixInput Tag Tests', function () { cy.log('up to 3x3 entry') - cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) - cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/mi1_rowIncrement').click(); + cy.get('#\\/mi1_columnIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[kgfh]') + + cy.get('#\\/mi1_columnIncrement').click(); + cy.get('#\\/mi1_rowIncrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') }) @@ -1911,13 +1848,15 @@ describe('MatrixInput Tag Tests', function () { }) - it('prefill with transpose of vector', () => { + it('prefill with vector, start smaller', () => { cy.window().then(async (win) => { win.postMessage({ doenetML: ` a +

Number of rows:

+

Number of columns:

-

Matrix 1:

+

Matrix 1:

Matrix 2:

`}, "*"); }); @@ -1925,27 +1864,34 @@ describe('MatrixInput Tag Tests', function () { cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ab]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'a', 'b']]] + let matrixAst = ["matrix", ["tuple", 0, 0], ["tuple"]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - - cy.log('remove column') - cy.get('#\\/mi1_columnDecrement').click(); + cy.log('add row and column') + cy.get('#\\/mi1_columnIncrement').click(); + cy.get('#\\/mi1_rowIncrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[a]') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') }) @@ -1954,16 +1900,22 @@ describe('MatrixInput Tag Tests', function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'a']]] + console.log(stateVariables['/mi1'].stateValues.value) expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('change value') - cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + cy.get('#\\/mi1 textarea').type("{end}{backspace}e{enter}", { force: true }); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -1976,60 +1928,102 @@ describe('MatrixInput Tag Tests', function () { expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - - cy.log('restore column') - cy.get('#\\/mi1_columnIncrement').click(); + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb]') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'b']]] + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('add row') - cy.get('#\\/mi1_rowIncrement').click(); + cy.log('type f in second row') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb__]') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + cy.log('add column via mathinput') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') }) cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb__]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", '_', '_']]] + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', '_'], ["tuple", 'f', '_']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('change values') - cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + cy.log('g and h in second column') cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2052,11 +2046,17 @@ describe('MatrixInput Tag Tests', function () { }); - cy.log('add row') - cy.get('#\\/mi1_rowIncrement').click(); + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2091,6 +2091,12 @@ describe('MatrixInput Tag Tests', function () { cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2120,17 +2126,19 @@ describe('MatrixInput Tag Tests', function () { cy.log('down to one entry') - cy.get('#\\/mi1_rowDecrement').click(); - cy.get('#\\/mi1_columnDecrement').click(); - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') - - cy.get('#\\/mi1_rowDecrement').click(); + cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') @@ -2148,6 +2156,12 @@ describe('MatrixInput Tag Tests', function () { cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') }) @@ -2164,16 +2178,17 @@ describe('MatrixInput Tag Tests', function () { cy.log('up to 3x3 entry') - cy.get('#\\/mi1_rowIncrement').click(); - cy.get('#\\/mi1_columnIncrement').click(); - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[kgfh]') - - cy.get('#\\/mi1_columnIncrement').click(); - cy.get('#\\/mi1_rowIncrement').click(); + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') }) @@ -2213,7 +2228,7 @@ describe('MatrixInput Tag Tests', function () { }) - it('prefill with transpose of vector, start smaller', () => { + it('prefill with altvector, start smaller', () => { cy.window().then(async (win) => { win.postMessage({ doenetML: ` @@ -2221,7 +2236,7 @@ describe('MatrixInput Tag Tests', function () {

Number of rows:

Number of columns:

-

Matrix 1:

+

Matrix 1:

Matrix 2:

`}, "*"); }); @@ -2296,7 +2311,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('add row') cy.get('#\\/mi1_rowIncrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_]') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb]') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') @@ -2308,13 +2323,13 @@ describe('MatrixInput Tag Tests', function () { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", '_']]] + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); @@ -2348,7 +2363,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('add column via mathinput') cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ebf_]') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') @@ -2360,7 +2375,7 @@ describe('MatrixInput Tag Tests', function () { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') @@ -2368,11 +2383,11 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ebf_]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", 'f', '_']]] + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', '_'], ["tuple", 'f', '_']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); @@ -2593,15 +2608,13 @@ describe('MatrixInput Tag Tests', function () { }) - it('prefill with transpose of vector, start smaller, alternative format', () => { + it('prefill with transpose of vector', () => { cy.window().then(async (win) => { win.postMessage({ doenetML: ` a -

Number of rows:

-

Number of columns:

-

Matrix 1:

+

Matrix 1:

Matrix 2:

`}, "*"); }); @@ -2609,34 +2622,27 @@ describe('MatrixInput Tag Tests', function () { cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ab]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 0, 0], ["tuple"]] + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'a', 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('add row and column') - cy.get('#\\/mi1_columnIncrement').click(); - cy.get('#\\/mi1_rowIncrement').click(); + + cy.log('remove column') + cy.get('#\\/mi1_columnDecrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[a]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') }) @@ -2645,22 +2651,16 @@ describe('MatrixInput Tag Tests', function () { cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'a']]] - console.log(stateVariables['/mi1'].stateValues.value) expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); + cy.log('change value') - cy.get('#\\/mi1 textarea').type("{end}{backspace}e{enter}", { force: true }); + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2673,69 +2673,32 @@ describe('MatrixInput Tag Tests', function () { expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('add row') - cy.get('#\\/mi1_rowIncrement').click(); - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_]') - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_]') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", '_']]] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); - }); - cy.log('type f in second row') - cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + cy.log('restore column') + cy.get('#\\/mi1_columnIncrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('add column via mathinput') - cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ebf_]') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb__]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2743,32 +2706,27 @@ describe('MatrixInput Tag Tests', function () { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ebf_]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb__]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", 'f', '_']]] + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", '_', '_']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); }); - cy.log('g and h in second column') + cy.log('change values') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2791,17 +2749,11 @@ describe('MatrixInput Tag Tests', function () { }); - cy.log('add row via mathinput') - cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2836,12 +2788,6 @@ describe('MatrixInput Tag Tests', function () { cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2871,17 +2817,15 @@ describe('MatrixInput Tag Tests', function () { cy.log('down to one entry') - cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) - cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/mi1_rowDecrement').click(); + cy.get('#\\/mi1_columnDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + + cy.get('#\\/mi1_rowDecrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) @@ -2901,12 +2845,6 @@ describe('MatrixInput Tag Tests', function () { cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') }) @@ -2923,17 +2861,16 @@ describe('MatrixInput Tag Tests', function () { cy.log('up to 3x3 entry') - cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) - cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/mi1_rowIncrement').click(); + cy.get('#\\/mi1_columnIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[kgfh]') + + cy.get('#\\/mi1_columnIncrement').click(); + cy.get('#\\/mi1_rowIncrement').click(); cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') }) @@ -2973,73 +2910,4002 @@ describe('MatrixInput Tag Tests', function () { }) - it('bind to matrix', () => { + it('prefill with transpose of altvector', () => { cy.window().then(async (win) => { win.postMessage({ doenetML: ` a -

Number of rows:

-

Number of columns:

-

Matrix 1: \\begin{matrix}a & b\\\\c & d\\end{matrix}

-

Matrix 2:

-

Matrix 3:

+

Matrix 1:

+

Matrix 2:

`}, "*"); }); cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') }) cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') - }) - cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('d') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[abcd]') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[abcd]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ab]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'a', 'b'], ["tuple", 'c', 'd']]] + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'a', 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); }); - cy.log('change entries') - cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) - cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) - cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) - cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + cy.log('remove column') + cy.get('#\\/mi1_columnDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[a]') - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[a]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'a']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('restore column') + cy.get('#\\/mi1_columnIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb]') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'b']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb__]') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb__]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change values') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change third row values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}i{enter}", { force: true }) + cy.get('#\\/mi1_component_2_1 textarea').type("{end}{backspace}j{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", 'i', 'j']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('down to one entry') + cy.get('#\\/mi1_rowDecrement').click(); + cy.get('#\\/mi1_columnDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + + cy.get('#\\/mi1_rowDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}k{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[k]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'k']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + + cy.log('up to 3x3 entry') + cy.get('#\\/mi1_rowIncrement').click(); + cy.get('#\\/mi1_columnIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[kgfh]') + + cy.get('#\\/mi1_columnIncrement').click(); + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_1_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('prefill with transpose of vector, start smaller', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Matrix 1:

+

Matrix 2:

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 0, 0], ["tuple"]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row and column') + cy.get('#\\/mi1_columnIncrement').click(); + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[a]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[a]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'a']]] + console.log(stateVariables['/mi1'].stateValues.value) + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change value') + cy.get('#\\/mi1 textarea').type("{end}{backspace}e{enter}", { force: true }); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('type f in second row') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add column via mathinput') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ebf_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ebf_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", 'f', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('g and h in second column') + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change third row values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}i{enter}", { force: true }) + cy.get('#\\/mi1_component_2_1 textarea').type("{end}{backspace}j{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", 'i', 'j']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('down to one entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}k{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[k]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'k']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + + cy.log('up to 3x3 entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_1_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('prefill with transpose of altvector, start smaller', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Matrix 1:

+

Matrix 2:

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 0, 0], ["tuple"]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row and column') + cy.get('#\\/mi1_columnIncrement').click(); + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[a]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[a]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'a']]] + console.log(stateVariables['/mi1'].stateValues.value) + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change value') + cy.get('#\\/mi1 textarea').type("{end}{backspace}e{enter}", { force: true }); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('type f in second row') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add column via mathinput') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ebf_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ebf_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", 'f', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('g and h in second column') + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change third row values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}i{enter}", { force: true }) + cy.get('#\\/mi1_component_2_1 textarea').type("{end}{backspace}j{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", 'i', 'j']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('down to one entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}k{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[k]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'k']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + + cy.log('up to 3x3 entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_1_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('prefill with transpose of vector, start smaller, alternative format', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Matrix 1:

+

Matrix 2:

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 0, 0], ["tuple"]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row and column') + cy.get('#\\/mi1_columnIncrement').click(); + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[a]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[a]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'a']]] + console.log(stateVariables['/mi1'].stateValues.value) + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change value') + cy.get('#\\/mi1 textarea').type("{end}{backspace}e{enter}", { force: true }); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('type f in second row') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add column via mathinput') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ebf_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ebf_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", 'f', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('g and h in second column') + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change third row values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}i{enter}", { force: true }) + cy.get('#\\/mi1_component_2_1 textarea').type("{end}{backspace}j{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", 'i', 'j']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('down to one entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}k{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[k]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'k']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + + cy.log('up to 3x3 entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_1_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('prefill with transpose of altvector, start smaller, alternative format', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Matrix 1:

+

Matrix 2:

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 0, 0], ["tuple"]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row and column') + cy.get('#\\/mi1_columnIncrement').click(); + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[a]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[a]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'a']]] + console.log(stateVariables['/mi1'].stateValues.value) + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change value') + cy.get('#\\/mi1 textarea').type("{end}{backspace}e{enter}", { force: true }); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('type f in second row') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add column via mathinput') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ebf_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ebf_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", 'f', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + cy.log('g and h in second column') + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change third row values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}i{enter}", { force: true }) + cy.get('#\\/mi1_component_2_1 textarea').type("{end}{backspace}j{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", 'i', 'j']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('down to one entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}k{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[k]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'k']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + + cy.log('up to 3x3 entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_1_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('bind to matrix', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Matrix 1: \\begin{matrix}a & b\\\\c & d\\end{matrix}

+

Matrix 2:

+

Matrix 3:

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('d') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[abcd]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[abcd]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'a', 'b'], ["tuple", 'c', 'd']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change entries') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change third row values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}i{enter}", { force: true }) + cy.get('#\\/mi1_component_2_1 textarea').type("{end}{backspace}j{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", 'i', 'j']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('down to one entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}k{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[k]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[k]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'k']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + + cy.log('up to 3x3 entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_1_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('bind to matrix, ignore size via definition', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Matrix 1: \\begin{matrix}a & b\\\\c & d\\end{matrix}

+

Matrix 2:

+

Matrix 3:

+ +

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('5') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('d') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[abcd]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[abcd]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'a', 'b'], ["tuple", 'c', 'd']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ebcd]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('5') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('d') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ebcd]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ebcd]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", 'c', 'd']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('remove row') + cy.get('#\\/mi1_rowDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('5') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eb]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'b']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('ignore change in numRows') + cy.get('#\\/numRows textarea').type("{end}{backspace}9{enter}", { force: true }) + + // wait for core to responds to change in textinput, so know have waited long enough + cy.get("#\\/ti_input").type("wait{enter}"); + + cy.get("#\\/t").should('have.text', 'wait'); + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('9') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('5') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eb]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'b']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('bind to vector', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Vector 1: (a,b)

+

Matrix 2:

+

Matrix 3:

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(a,b)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ab]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let vectorAst = ["tuple", "a", "b"] + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'a'], ["tuple", 'b']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change values') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let vectorAst = ["tuple", "e", "f"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row, original stays a vector'); + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,_)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,_)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣ef_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", '_']]] + let vectorAst = ["tuple", "e", "f", "_"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}z{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,z)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,z)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efz⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'z']]] + let vectorAst = ["tuple", "e", "f", "z"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('remove row') + cy.get('#\\/mi1_rowDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let vectorAst = ["tuple", "e", "f"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('get value back when add rows') + cy.get('#\\/numRows textarea').type("{end}{backspace}4{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,z,_)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') + }) + cy.get(`#\\/mi1_component_3_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,z,_)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢\n⎢\n⎢\n⎢⎣efz_⎤⎥\n⎥\n⎥\n⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 4, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'z'], ["tuple", '_']]] + let vectorAst = ["tuple", "e", "f", "z", "_"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}{enter}", { force: true }) + cy.get('#\\/mi1_component_3_0 textarea').type("{end}{backspace}y{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,_,y)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_3_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('y') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,_,y)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢\n⎢\n⎢\n⎢⎣ef_y⎤⎥\n⎥\n⎥\n⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 4, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", '_'], ["tuple", 'y']]] + let vectorAst = ["tuple", "e", "f", "_", "y"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('back to 2D vector') + cy.get('#\\/numRows textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let vectorAst = ["tuple", "e", "f"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add column via mathinput') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', '_'], ["tuple", 'f', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('g and h in second column') + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change third row values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}i{enter}", { force: true }) + cy.get('#\\/mi1_component_2_1 textarea').type("{end}{backspace}j{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", 'i', 'j']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('down to one entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}k{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[k]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[k]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'k']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + + cy.log('up to 3x3 entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_1_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('bind to altvector', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Vector 1: ⟨a,b⟩

+

Matrix 2:

+

Matrix 3:

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨a,b⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ab]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let vectorAst = ["altvector", "a", "b"] + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'a'], ["tuple", 'b']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change values') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let vectorAst = ["altvector", "e", "f"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add row, original stays a vector'); + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f,_⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f,_⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣ef_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", '_']]] + let vectorAst = ["altvector", "e", "f", "_"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}z{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f,z⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f,z⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efz⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'z']]] + let vectorAst = ["altvector", "e", "f", "z"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('remove row') + cy.get('#\\/mi1_rowDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let vectorAst = ["altvector", "e", "f"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('get value back when add rows') + cy.get('#\\/numRows textarea').type("{end}{backspace}4{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f,z,_⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') + }) + cy.get(`#\\/mi1_component_3_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f,z,_⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢\n⎢\n⎢\n⎢⎣efz_⎤⎥\n⎥\n⎥\n⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 4, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'z'], ["tuple", '_']]] + let vectorAst = ["altvector", "e", "f", "z", "_"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}{enter}", { force: true }) + cy.get('#\\/mi1_component_3_0 textarea').type("{end}{backspace}y{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f,_,y⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_3_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('y') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f,_,y⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢\n⎢\n⎢\n⎢⎣ef_y⎤⎥\n⎥\n⎥\n⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 4, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", '_'], ["tuple", 'y']]] + let vectorAst = ["altvector", "e", "f", "_", "y"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('back to 2D vector') + cy.get('#\\/numRows textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let vectorAst = ["altvector", "e", "f"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add column via mathinput') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', '_'], ["tuple", 'f', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('g and h in second column') + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egfh]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfh__⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change third row values') + cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}i{enter}", { force: true }) + cy.get('#\\/mi1_component_2_1 textarea').type("{end}{backspace}j{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣egfhij⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", 'f', 'h'], ["tuple", 'i', 'j']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('down to one entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}1{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}1{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'e']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change value') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}k{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[k]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[k]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[k]') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 1], ["tuple", ["tuple", 'k']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + + cy.log('up to 3x3 entry') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('k') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('h') + }) + cy.get(`#\\/mi1_component_1_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('i') + }) + cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') + }) + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('bind to vector, ignore size via definition', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Vector 1: (a,b,c)

+

Matrix 2:

+

Matrix 3:

+ +

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(a,b,c)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣abc⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let vectorAst = ["tuple", "a", "b", "c"] + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'a'], ["tuple", 'b'], ["tuple", 'c']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change values') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,c)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,c)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efc⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'c']]] + let vectorAst = ["tuple", "e", "f", "c"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('ignore change in numColumns') + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + // wait for core to responds to change in textinput, so know have waited long enough + cy.get("#\\/ti_input").type("wait{enter}"); + + cy.get("#\\/t").should('have.text', 'wait'); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,c)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,c)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efc⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'c']]] + let vectorAst = ["tuple", "e", "f", "c"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('remove row') + cy.get('#\\/mi1_rowDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f)') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f)') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let vectorAst = ["tuple", "e", "f"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add column') + cy.get('#\\/mi1_columnIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', '_'], ["tuple", 'f', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('bind to altvector, ignore size via definition', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Vector 1: ⟨a,b,c⟩

+

Matrix 2:

+

Matrix 3:

+ +

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨a,b,c⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣abc⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let vectorAst = ["altvector", "a", "b", "c"] + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'a'], ["tuple", 'b'], ["tuple", 'c']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change values') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f,c⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f,c⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efc⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'c']]] + let vectorAst = ["altvector", "e", "f", "c"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('ignore change in numColumns') + cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) + + // wait for core to responds to change in textinput, so know have waited long enough + cy.get("#\\/ti_input").type("wait{enter}"); + + cy.get("#\\/t").should('have.text', 'wait'); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f,c⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f,c⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efc⎤⎥⎦') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'c']]] + let vectorAst = ["altvector", "e", "f", "c"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('remove row') + cy.get('#\\/mi1_rowDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f⟩') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f⟩') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] + let vectorAst = ["altvector", "e", "f"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add column') + cy.get('#\\/mi1_columnIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', '_'], ["tuple", 'f', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + }) + + it('bind to transpose of vector', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Vector 1: (a,b)^T

+

Matrix 2:

+

Matrix 3:

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(a,b)T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ab]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let vectorAst = ["^", ["tuple", "a", "b"], "T"]; + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'a', 'b']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change values') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] + let vectorAst = ["^", ["tuple", "e", "g"], "T"]; + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('add column, original stays a vector'); + cy.get('#\\/mi1_columnIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,_)T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,_)T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'g', '_']]] + let vectorAst = ["^", ["tuple", "e", "g", "_"], "T"]; + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change value') + cy.get('#\\/mi1_component_0_2 textarea').type("{end}{backspace}z{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,z)T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,z)T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egz]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'g', 'z']]] + let vectorAst = ["^", ["tuple", "e", "g", "z"], "T"]; + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('remove column') + cy.get('#\\/mi1_columnDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] + let vectorAst = ["^", ["tuple", "e", "g"], "T"]; + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('get value back when add columns') + cy.get('#\\/numColumns textarea').type("{end}{backspace}4{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,z,_)T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') + }) + cy.get(`#\\/mi1_component_0_3 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,z,_)T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egz_]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 4], ["tuple", ["tuple", 'e', 'g', 'z', '_']]] + let vectorAst = ["^", ["tuple", "e", "g", "z", "_"], "T"]; + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('change values') + cy.get('#\\/mi1_component_0_2 textarea').type("{end}{backspace}{enter}", { force: true }) + cy.get('#\\/mi1_component_0_3 textarea').type("{end}{backspace}y{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,_,y)T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_0_3 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('y') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,_,y)T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg_y]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 4], ["tuple", ["tuple", 'e', 'g', '_', 'y']]] + let vectorAst = ["^", ["tuple", "e", "g", "_", "y"], "T"]; + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('back to 2D vector transpose') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] + let vectorAst = ["^", ["tuple", "e", "g"], "T"]; + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eg__]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eg__]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg__]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('f and h in second row') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') }) cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { @@ -3195,7 +7061,6 @@ describe('MatrixInput Tag Tests', function () { }); - cy.log('up to 3x3 entry') cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) @@ -3249,153 +7114,7 @@ describe('MatrixInput Tag Tests', function () { }) - it('bind to matrix, ignore size via definition', () => { - cy.window().then(async (win) => { - win.postMessage({ - doenetML: ` - a -

Number of rows:

-

Number of columns:

- -

Matrix 1: \\begin{matrix}a & b\\\\c & d\\end{matrix}

-

Matrix 2:

-

Matrix 3:

- -

- `}, "*"); - }); - - - cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('5') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') - }) - cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') - }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') - }) - cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('d') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[abcd]') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[abcd]') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'a', 'b'], ["tuple", 'c', 'd']]] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - cy.log('change value') - cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ebcd]') - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('5') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') - }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') - }) - cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('d') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ebcd]') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ebcd]') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'b'], ["tuple", 'c', 'd']]] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - - cy.log('remove row') - cy.get('#\\/mi1_rowDecrement').click(); - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eb]') - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('5') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb]') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eb]') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'b']]] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - - cy.log('ignore change in numRows') - cy.get('#\\/numRows textarea').type("{end}{backspace}9{enter}", { force: true }) - - // wait for core to responds to change in textinput, so know have waited long enough - cy.get("#\\/ti_input").type("wait{enter}"); - - cy.get("#\\/t").should('have.text', 'wait'); - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('9') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('5') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eb]') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eb]') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'b']]] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - - }) - - it('bind to vector', () => { + it('bind to transpose of altvector', () => { cy.window().then(async (win) => { win.postMessage({ doenetML: ` @@ -3403,7 +7122,7 @@ describe('MatrixInput Tag Tests', function () {

Number of rows:

Number of columns:

-

Vector 1: (a,b)

+

Vector 1: ⟨a,b⟩^T

Matrix 2:

Matrix 3:

`}, "*"); @@ -3413,24 +7132,24 @@ describe('MatrixInput Tag Tests', function () { cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') }) cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(a,b)') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨a,b⟩T') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ab]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let vectorAst = ["tuple", "a", "b"] - let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'a'], ["tuple", 'b']]] + let vectorAst = ["^", ["altvector", "a", "b"], "T"]; + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'a', 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -3438,160 +7157,159 @@ describe('MatrixInput Tag Tests', function () { cy.log('change values') cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) - cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f)') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g⟩T') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') }) cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] - let vectorAst = ["tuple", "e", "f"] + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] + let vectorAst = ["^", ["altvector", "e", "g"], "T"]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); }); - cy.log('add row, original stays a vector'); - cy.get('#\\/mi1_rowIncrement').click(); + cy.log('add column, original stays a vector'); + cy.get('#\\/mi1_columnIncrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,_)') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g,_⟩T') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') }) cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,_)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣ef_⎤⎥⎦') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g,_⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg_]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", '_']]] - let vectorAst = ["tuple", "e", "f", "_"] + let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'g', '_']]] + let vectorAst = ["^", ["altvector", "e", "g", "_"], "T"]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); }); - cy.log('change value') - cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}z{enter}", { force: true }) + cy.get('#\\/mi1_component_0_2 textarea').type("{end}{backspace}z{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,z)') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g,z⟩T') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') }) cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,z)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efz⎤⎥⎦') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g,z⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egz]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'z']]] - let vectorAst = ["tuple", "e", "f", "z"] + let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'g', 'z']]] + let vectorAst = ["^", ["altvector", "e", "g", "z"], "T"]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); }); - cy.log('remove row') - cy.get('#\\/mi1_rowDecrement').click(); + cy.log('remove column') + cy.get('#\\/mi1_columnDecrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f)') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g⟩T') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') }) cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] - let vectorAst = ["tuple", "e", "f"] + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] + let vectorAst = ["^", ["altvector", "e", "g"], "T"]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); }); - cy.log('get value back when add rows') - cy.get('#\\/numRows textarea').type("{end}{backspace}4{enter}", { force: true }) + cy.log('get value back when add columns') + cy.get('#\\/numColumns textarea').type("{end}{backspace}4{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,z,_)') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g,z,_⟩T') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') }) cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') }) - cy.get(`#\\/mi1_component_3_0 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_0_3 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,z,_)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢\n⎢\n⎢\n⎢⎣efz_⎤⎥\n⎥\n⎥\n⎥⎦') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g,z,_⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egz_]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 4, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'z'], ["tuple", '_']]] - let vectorAst = ["tuple", "e", "f", "z", "_"] + let matrixAst = ["matrix", ["tuple", 1, 4], ["tuple", ["tuple", 'e', 'g', 'z', '_']]] + let vectorAst = ["^", ["altvector", "e", "g", "z", "_"], "T"]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -3599,75 +7317,76 @@ describe('MatrixInput Tag Tests', function () { cy.log('change values') - cy.get('#\\/mi1_component_2_0 textarea').type("{end}{backspace}{enter}", { force: true }) - cy.get('#\\/mi1_component_3_0 textarea').type("{end}{backspace}y{enter}", { force: true }) + cy.get('#\\/mi1_component_0_2 textarea').type("{end}{backspace}{enter}", { force: true }) + cy.get('#\\/mi1_component_0_3 textarea').type("{end}{backspace}y{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,_,y)') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g,_,y⟩T') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') }) cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('4') }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get(`#\\/mi1_component_3_0 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_0_3 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('y') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,_,y)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢\n⎢\n⎢\n⎢⎣ef_y⎤⎥\n⎥\n⎥\n⎥⎦') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g,_,y⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg_y]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 4, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", '_'], ["tuple", 'y']]] - let vectorAst = ["tuple", "e", "f", "_", "y"] + let matrixAst = ["matrix", ["tuple", 1, 4], ["tuple", ["tuple", 'e', 'g', '_', 'y']]] + let vectorAst = ["^", ["altvector", "e", "g", "_", "y"], "T"]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); }); - cy.log('back to 2D vector') - cy.get('#\\/numRows textarea').type("{end}{backspace}2{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f)') + cy.log('back to 2D vector transpose') + cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g⟩T') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') }) cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') }) cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] - let vectorAst = ["tuple", "e", "f"] + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] + let vectorAst = ["^", ["altvector", "e", "g"], "T"]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); }); - cy.log('add column via mathinput') - cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) + cy.log('add row via mathinput') + cy.get('#\\/numRows textarea').type("{end}{backspace}2{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[eg__]') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') @@ -3679,27 +7398,27 @@ describe('MatrixInput Tag Tests', function () { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') }) cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[eg__]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg__]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', '_'], ["tuple", 'f', '_']]] + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'g'], ["tuple", '_', '_']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); }); - cy.log('g and h in second column') - cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) + cy.log('f and h in second row') + cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) cy.get('#\\/mi1_component_1_1 textarea').type("{end}{backspace}h{enter}", { force: true }) cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[egfh]') @@ -3872,7 +7591,6 @@ describe('MatrixInput Tag Tests', function () { }); - cy.log('up to 3x3 entry') cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) @@ -3909,199 +7627,15 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_2_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('j') }) - cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - - }) - - it('bind to vector, ignore size via definition', () => { - cy.window().then(async (win) => { - win.postMessage({ - doenetML: ` - a -

Number of rows:

-

Number of columns:

- -

Vector 1: (a,b,c)

-

Matrix 2:

-

Matrix 3:

- -

- `}, "*"); - }); - - - cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') - }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') - }) - cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(a,b,c)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣abc⎤⎥⎦') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let vectorAst = ["tuple", "a", "b", "c"] - let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'a'], ["tuple", 'b'], ["tuple", 'c']]] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - cy.log('change values') - cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) - cy.get('#\\/mi1_component_1_0 textarea').type("{end}{backspace}f{enter}", { force: true }) - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,c)') - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') - }) - cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,c)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efc⎤⎥⎦') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'c']]] - let vectorAst = ["tuple", "e", "f", "c"] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - - cy.log('ignore change in numColumns') - cy.get('#\\/numColumns textarea').type("{end}{backspace}3{enter}", { force: true }) - - // wait for core to responds to change in textinput, so know have waited long enough - cy.get("#\\/ti_input").type("wait{enter}"); - - cy.get("#\\/t").should('have.text', 'wait'); - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f,c)') - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') - }) - cy.get(`#\\/mi1_component_2_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f,c)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣efc⎤⎥⎦') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 3, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f'], ["tuple", 'c']]] - let vectorAst = ["tuple", "e", "f", "c"] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - - cy.log('remove row') - cy.get('#\\/mi1_rowDecrement').click(); - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,f)') - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') - }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,f)') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 1], ["tuple", ["tuple", 'e'], ["tuple", 'f']]] - let vectorAst = ["tuple", "e", "f"] - expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); - expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); - expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); - }); - - cy.log('add column') - cy.get('#\\/mi1_columnIncrement').click(); - - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[e_f_]') - - cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') - }) - cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') - }) - cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') - }) - cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') - }) - cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + cy.get(`#\\/mi1_component_2_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') - cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[e_f_]') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '⎡⎢⎣kg_fh_ij_⎤⎥⎦') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', '_'], ["tuple", 'f', '_']]] + let matrixAst = ["matrix", ["tuple", 3, 3], ["tuple", ["tuple", 'k', 'g', '_'], ["tuple", 'f', 'h', '_'], ["tuple", 'i', 'j', '_']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4110,7 +7644,7 @@ describe('MatrixInput Tag Tests', function () { }) - it('bind to transpose of vector', () => { + it('bind to transpose of vector, alternative format', () => { cy.window().then(async (win) => { win.postMessage({ doenetML: ` @@ -4118,7 +7652,7 @@ describe('MatrixInput Tag Tests', function () {

Number of rows:

Number of columns:

-

Vector 1: (a,b)^T

+

Vector 1: (a,b)'

Matrix 2:

Matrix 3:

`}, "*"); @@ -4139,12 +7673,12 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(a,b)T') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(a,b)′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ab]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let vectorAst = ["^", ["tuple", "a", "b"], "T"]; + let vectorAst = ["prime", ["tuple", "a", "b"]]; let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'a', 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); @@ -4155,7 +7689,7 @@ describe('MatrixInput Tag Tests', function () { cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)T') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4169,13 +7703,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)T') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] - let vectorAst = ["^", ["tuple", "e", "g"], "T"]; + let vectorAst = ["prime", ["tuple", "e", "g"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4184,7 +7718,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('add column, original stays a vector'); cy.get('#\\/mi1_columnIncrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,_)T') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,_)′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4201,13 +7735,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,_)T') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,_)′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg_]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'g', '_']]] - let vectorAst = ["^", ["tuple", "e", "g", "_"], "T"]; + let vectorAst = ["prime", ["tuple", "e", "g", "_"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4216,7 +7750,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('change value') cy.get('#\\/mi1_component_0_2 textarea').type("{end}{backspace}z{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,z)T') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,z)′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4233,13 +7767,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,z)T') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,z)′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egz]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'g', 'z']]] - let vectorAst = ["^", ["tuple", "e", "g", "z"], "T"]; + let vectorAst = ["prime", ["tuple", "e", "g", "z"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4249,7 +7783,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('remove column') cy.get('#\\/mi1_columnDecrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)T') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4263,13 +7797,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)T') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] - let vectorAst = ["^", ["tuple", "e", "g"], "T"]; + let vectorAst = ["prime", ["tuple", "e", "g"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4279,7 +7813,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('get value back when add columns') cy.get('#\\/numColumns textarea').type("{end}{backspace}4{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,z,_)T') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,z,_)′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4299,13 +7833,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_3 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,z,_)T') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,z,_)′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egz_]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 4], ["tuple", ["tuple", 'e', 'g', 'z', '_']]] - let vectorAst = ["^", ["tuple", "e", "g", "z", "_"], "T"]; + let vectorAst = ["prime", ["tuple", "e", "g", "z", "_"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4316,7 +7850,7 @@ describe('MatrixInput Tag Tests', function () { cy.get('#\\/mi1_component_0_2 textarea').type("{end}{backspace}{enter}", { force: true }) cy.get('#\\/mi1_component_0_3 textarea').type("{end}{backspace}y{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,_,y)T') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,_,y)′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4336,13 +7870,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_3 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('y') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,_,y)T') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,_,y)′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg_y]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 4], ["tuple", ["tuple", 'e', 'g', '_', 'y']]] - let vectorAst = ["^", ["tuple", "e", "g", "_", "y"], "T"]; + let vectorAst = ["prime", ["tuple", "e", "g", "_", "y"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4352,7 +7886,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('back to 2D vector transpose') cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)T') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4366,13 +7900,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)T') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] - let vectorAst = ["^", ["tuple", "e", "g"], "T"]; + let vectorAst = ["prime", ["tuple", "e", "g"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4648,7 +8182,7 @@ describe('MatrixInput Tag Tests', function () {

Number of rows:

Number of columns:

-

Vector 1: (a,b)'

+

Vector 1: ⟨a,b⟩'

Matrix 2:

Matrix 3:

`}, "*"); @@ -4669,12 +8203,12 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(a,b)′') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨a,b⟩′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ab]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - let vectorAst = ["prime", ["tuple", "a", "b"]]; + let vectorAst = ["prime", ["altvector", "a", "b"]]; let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'a', 'b']]] expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); @@ -4685,7 +8219,7 @@ describe('MatrixInput Tag Tests', function () { cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}g{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)′') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g⟩′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4699,13 +8233,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)′') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g⟩′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] - let vectorAst = ["prime", ["tuple", "e", "g"]]; + let vectorAst = ["prime", ["altvector", "e", "g"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4714,7 +8248,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('add column, original stays a vector'); cy.get('#\\/mi1_columnIncrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,_)′') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g,_⟩′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4731,13 +8265,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,_)′') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g,_⟩′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg_]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'g', '_']]] - let vectorAst = ["prime", ["tuple", "e", "g", "_"]]; + let vectorAst = ["prime", ["altvector", "e", "g", "_"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4746,7 +8280,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('change value') cy.get('#\\/mi1_component_0_2 textarea').type("{end}{backspace}z{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,z)′') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g,z⟩′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4763,13 +8297,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('z') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,z)′') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g,z⟩′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egz]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'g', 'z']]] - let vectorAst = ["prime", ["tuple", "e", "g", "z"]]; + let vectorAst = ["prime", ["altvector", "e", "g", "z"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4779,7 +8313,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('remove column') cy.get('#\\/mi1_columnDecrement').click(); - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)′') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g⟩′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4793,13 +8327,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)′') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g⟩′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] - let vectorAst = ["prime", ["tuple", "e", "g"]]; + let vectorAst = ["prime", ["altvector", "e", "g"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4809,7 +8343,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('get value back when add columns') cy.get('#\\/numColumns textarea').type("{end}{backspace}4{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,z,_)′') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g,z,_⟩′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4829,13 +8363,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_3 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,z,_)′') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g,z,_⟩′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[egz_]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 4], ["tuple", ["tuple", 'e', 'g', 'z', '_']]] - let vectorAst = ["prime", ["tuple", "e", "g", "z", "_"]]; + let vectorAst = ["prime", ["altvector", "e", "g", "z", "_"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4846,7 +8380,7 @@ describe('MatrixInput Tag Tests', function () { cy.get('#\\/mi1_component_0_2 textarea').type("{end}{backspace}{enter}", { force: true }) cy.get('#\\/mi1_component_0_3 textarea').type("{end}{backspace}y{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g,_,y)′') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g,_,y⟩′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4866,13 +8400,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_3 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('y') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g,_,y)′') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g,_,y⟩′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg_y]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 4], ["tuple", ["tuple", 'e', 'g', '_', 'y']]] - let vectorAst = ["prime", ["tuple", "e", "g", "_", "y"]]; + let vectorAst = ["prime", ["altvector", "e", "g", "_", "y"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -4882,7 +8416,7 @@ describe('MatrixInput Tag Tests', function () { cy.log('back to 2D vector transpose') cy.get('#\\/numColumns textarea').type("{end}{backspace}2{enter}", { force: true }) - cy.get("#\\/m1 .mjx-mrow").should('contain.text', '(e,g)′') + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,g⟩′') cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') @@ -4896,13 +8430,13 @@ describe('MatrixInput Tag Tests', function () { cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('g') }) - cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '(e,g)′') + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,g⟩′') cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[eg]') cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'g']]] - let vectorAst = ["prime", ["tuple", "e", "g"]]; + let vectorAst = ["prime", ["altvector", "e", "g"]]; expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); @@ -5354,6 +8888,192 @@ describe('MatrixInput Tag Tests', function () { }); + }) + + it('bind to transpose of vector, ignore size via definition', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

Number of rows:

+

Number of columns:

+ +

Vector 1: ⟨a,b,c⟩^T

+

Matrix 2:

+

Matrix 3:

+ +

+ `}, "*"); + }); + + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('a') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('b') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨a,b,c⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[abc]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let vectorAst = ["^", ["altvector", "a", "b", "c"], "T"] + let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'a', 'b', 'c']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + cy.log('change values') + cy.get('#\\/mi1_component_0_0 textarea').type("{end}{backspace}e{enter}", { force: true }) + cy.get('#\\/mi1_component_0_1 textarea').type("{end}{backspace}f{enter}", { force: true }) + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f,c⟩T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('7') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f,c⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[efc]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'f', 'c']]] + let vectorAst = ["^", ["altvector", "e", "f", "c"], "T"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('ignore change in numRows') + cy.get('#\\/numRows textarea').type("{end}{backspace}3{enter}", { force: true }) + + + // wait for core to responds to change in textinput, so know have waited long enough + cy.get("#\\/ti_input").type("wait{enter}"); + + cy.get("#\\/t").should('have.text', 'wait'); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f,c⟩T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('1') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_0_2 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('c') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f,c⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[efc]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 3], ["tuple", ["tuple", 'e', 'f', 'c']]] + let vectorAst = ["^", ["altvector", "e", "f", "c"], "T"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('remove column') + cy.get('#\\/mi1_columnDecrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '⟨e,f⟩T') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('3') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '⟨e,f⟩T') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 1, 2], ["tuple", ["tuple", 'e', 'f']]] + let vectorAst = ["^", ["altvector", "e", "f"], "T"] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(vectorAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + + cy.log('add row') + cy.get('#\\/mi1_rowIncrement').click(); + + cy.get("#\\/m1 .mjx-mrow").should('contain.text', '[ef__]') + + cy.get(`#\\/numRows .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/numColumns .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('2') + }) + cy.get(`#\\/mi1_component_0_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('e') + }) + cy.get(`#\\/mi1_component_1_0 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get(`#\\/mi1_component_0_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('f') + }) + cy.get(`#\\/mi1_component_1_1 .mq-editable-field`).invoke('text').then((text) => { + expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, '')).equal('') + }) + cy.get("#\\/m1").find('.mjx-mrow').eq(0).should('have.text', '[ef__]') + cy.get("#\\/m2").find('.mjx-mrow').eq(0).should('have.text', '[ef__]') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let matrixAst = ["matrix", ["tuple", 2, 2], ["tuple", ["tuple", 'e', 'f'], ["tuple", '_', '_']]] + expect(stateVariables['/mi1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m1'].stateValues.value).eqls(matrixAst); + expect(stateVariables['/m2'].stateValues.value).eqls(matrixAst); + }); + + }) it('matrixinput eliminates multicharacter symbols', () => { diff --git a/cypress/e2e/DoenetML/tagSpecific/point.cy.js b/cypress/e2e/DoenetML/tagSpecific/point.cy.js index 11b3a5435a..05b93ea2a6 100644 --- a/cypress/e2e/DoenetML/tagSpecific/point.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/point.cy.js @@ -2064,6 +2064,42 @@ describe('Point Tag Tests', function () { expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 6, 5, 4]) }) + cy.log('create 2D point from altvector') + cy.get('#\\/coords textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 5,-2\\rangle {enter}", { force: true }) + + cy.get('#\\/Pcoords .mjx-mrow').should('contain.text', '(5,−2)'); + cy.get('#\\/Qcoords .mjx-mrow').should('contain.text', '(5,−2)'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect((stateVariables['/P'].stateValues.xs)).eqls([5, -2]) + expect((stateVariables['/P'].stateValues.coords)).eqls(["vector", 5, -2]) + expect((stateVariables['/Q'].stateValues.xs)).eqls([5, -2]) + expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 5, -2]) + }) + + + cy.log('move point P to (7,8)') + + cy.window().then(async (win) => { + win.callAction1({ + actionName: "movePoint", + componentName: "/P", + args: { x: 7, y: 8 } + }) + }); + + cy.get('#\\/Pcoords .mjx-mrow').should('contain.text', '(7,8)'); + cy.get('#\\/Qcoords .mjx-mrow').should('contain.text', '(7,8)'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect((stateVariables['/P'].stateValues.xs)).eqls([7, 8]) + expect((stateVariables['/P'].stateValues.coords)).eqls(["vector", 7, 8]) + expect((stateVariables['/Q'].stateValues.xs)).eqls([7, 8]) + expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 7, 8]) + }) + }); it('point sugar from single math', () => { @@ -2199,6 +2235,43 @@ describe('Point Tag Tests', function () { expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 6, 5, 4]) }) + + cy.log('create 2D point from altvector') + cy.get('#\\/coords textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 5,-2\\rangle {enter}", { force: true }) + + cy.get('#\\/Pcoords .mjx-mrow').should('contain.text', '(5,−2)'); + cy.get('#\\/Qcoords .mjx-mrow').should('contain.text', '(5,−2)'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect((stateVariables['/P'].stateValues.xs)).eqls([5, -2]) + expect((stateVariables['/P'].stateValues.coords)).eqls(["vector", 5, -2]) + expect((stateVariables['/Q'].stateValues.xs)).eqls([5, -2]) + expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 5, -2]) + }) + + + cy.log('move point P to (7,8)') + + cy.window().then(async (win) => { + win.callAction1({ + actionName: "movePoint", + componentName: "/P", + args: { x: 7, y: 8 } + }) + }); + + cy.get('#\\/Pcoords .mjx-mrow').should('contain.text', '(7,8)'); + cy.get('#\\/Qcoords .mjx-mrow').should('contain.text', '(7,8)'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect((stateVariables['/P'].stateValues.xs)).eqls([7, 8]) + expect((stateVariables['/P'].stateValues.coords)).eqls(["vector", 7, 8]) + expect((stateVariables['/Q'].stateValues.xs)).eqls([7, 8]) + expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 7, 8]) + }) + }); it('point from vector with sugared single math', () => { @@ -2334,6 +2407,43 @@ describe('Point Tag Tests', function () { expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 6, 5, 4]) }) + + cy.log('create 2D point from altvector') + cy.get('#\\/coords textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 5,-2\\rangle {enter}", { force: true }) + + cy.get('#\\/Pcoords .mjx-mrow').should('contain.text', '(5,−2)'); + cy.get('#\\/Qcoords .mjx-mrow').should('contain.text', '(5,−2)'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect((stateVariables['/P'].stateValues.xs)).eqls([5, -2]) + expect((stateVariables['/P'].stateValues.coords)).eqls(["vector", 5, -2]) + expect((stateVariables['/Q'].stateValues.xs)).eqls([5, -2]) + expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 5, -2]) + }) + + + cy.log('move point P to (7,8)') + + cy.window().then(async (win) => { + win.callAction1({ + actionName: "movePoint", + componentName: "/P", + args: { x: 7, y: 8 } + }) + }); + + cy.get('#\\/Pcoords .mjx-mrow').should('contain.text', '(7,8)'); + cy.get('#\\/Qcoords .mjx-mrow').should('contain.text', '(7,8)'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect((stateVariables['/P'].stateValues.xs)).eqls([7, 8]) + expect((stateVariables['/P'].stateValues.coords)).eqls(["vector", 7, 8]) + expect((stateVariables['/Q'].stateValues.xs)).eqls([7, 8]) + expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 7, 8]) + }) + }); it('point from copied vector with sugared single math', () => { @@ -2470,6 +2580,43 @@ describe('Point Tag Tests', function () { expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 6, 5, 4]) }) + + cy.log('create 2D point from altvector') + cy.get('#\\/coords textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 5,-2\\rangle {enter}", { force: true }) + + cy.get('#\\/Pcoords .mjx-mrow').should('contain.text', '(5,−2)'); + cy.get('#\\/Qcoords .mjx-mrow').should('contain.text', '(5,−2)'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect((stateVariables['/P'].stateValues.xs)).eqls([5, -2]) + expect((stateVariables['/P'].stateValues.coords)).eqls(["vector", 5, -2]) + expect((stateVariables['/Q'].stateValues.xs)).eqls([5, -2]) + expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 5, -2]) + }) + + + cy.log('move point P to (7,8)') + + cy.window().then(async (win) => { + win.callAction1({ + actionName: "movePoint", + componentName: "/P", + args: { x: 7, y: 8 } + }) + }); + + cy.get('#\\/Pcoords .mjx-mrow').should('contain.text', '(7,8)'); + cy.get('#\\/Qcoords .mjx-mrow').should('contain.text', '(7,8)'); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect((stateVariables['/P'].stateValues.xs)).eqls([7, 8]) + expect((stateVariables['/P'].stateValues.coords)).eqls(["vector", 7, 8]) + expect((stateVariables['/Q'].stateValues.xs)).eqls([7, 8]) + expect((stateVariables['/Q'].stateValues.coords)).eqls(["vector", 7, 8]) + }) + }); it('test invertible due to modifyIndirectly', () => { @@ -9828,7 +9975,7 @@ describe('Point Tag Tests', function () { cy.log('Create 3D point') - cy.get('#\\/originalCoords textarea').type('{end}{backspace}(2x,u/v{rightarrow},w^2{rightarrow}){enter}', { force: true }); + cy.get('#\\/originalCoords textarea').type('{end}{backspace}\\langle 2x,u/v{rightarrow},w^2{rightarrow}\\rangle {enter}', { force: true }); cy.get("#\\/point1p .mjx-mrow").should('contain.text', '(2x,uv,w2)') @@ -10229,7 +10376,7 @@ describe('Point Tag Tests', function () { cy.log('change the coordinates from point 2 coords') - cy.get("#\\/coords2b textarea").type('{ctrl+home}{shift+end}{backspace}(i,j,k){enter}', { force: true }); + cy.get("#\\/coords2b textarea").type('{ctrl+home}{shift+end}{backspace}\\langle i,j,k\\rangle {enter}', { force: true }); cy.get("#\\/point1p .mjx-mrow").should('contain.text', '(i,j,k)') diff --git a/cypress/e2e/DoenetML/tagSpecific/ray.cy.js b/cypress/e2e/DoenetML/tagSpecific/ray.cy.js index ed5378550f..6808a7dd11 100644 --- a/cypress/e2e/DoenetML/tagSpecific/ray.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/ray.cy.js @@ -5699,5 +5699,160 @@ describe('Ray Tag Tests', function () { }) + it('change ray by binding to values', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + + + +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ + `}, "*"); + }); + + // to wait for page to load + cy.get('#\\/vDirection .mjx-mrow').should('contain.text', '(1,0)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(1,0)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(0,0)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(1,0)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(1,0)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(0,0)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(1,0)'); + + cy.log('change head using alt vector') + cy.get('#\\/mivt textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 6,9{enter}", { force: true }); + + cy.get('#\\/vThrough .mjx-mrow').should('contain.text', '(6,9)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(0,0)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(0,0)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(6,9)'); + + + cy.log('change tail using alt vector') + cy.get('#\\/mive textarea').type("{ctrl+home}{shift+end}{backspace}\\langle -3,7{enter}", { force: true }); + cy.get('#\\/vEndpoint .mjx-mrow').should('contain.text', '(−3,7)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(3,16)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(3,16)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(6,9)'); + + cy.log('change displacement using alt vector') + cy.get('#\\/mivd textarea').type("{ctrl+home}{shift+end}{backspace}\\langle -4,1{enter}", { force: true }); + cy.get('#\\/vDirection .mjx-mrow').should('contain.text', '(−4,1)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(−7,8)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(−4,1)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(−7,8)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(−4,1)'); + + + cy.log('cannot change dimnension through displacement') + cy.get('#\\/mivd textarea').type("{ctrl+home}{shift+end}{backspace}(9,8,7{enter}", { force: true }); + cy.get('#\\/vDirection .mjx-mrow').should('contain.text', '(9,8)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(6,15)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(9,8)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(6,15)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(9,8)'); + + + cy.log('cannot change dimnension through tail') + cy.get('#\\/mive textarea').type("{ctrl+home}{shift+end}{backspace}(-5,-6,-7{enter}", { force: true }); + cy.get('#\\/vEndpoint .mjx-mrow').should('contain.text', '(−5,−6)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(4,2)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(9,8)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(4,2)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(9,8)'); + + + cy.log('cannot change dimnension through head') + cy.get('#\\/mivt textarea').type("{ctrl+home}{shift+end}{backspace}(9,-9,7{enter}", { force: true }); + cy.get('#\\/vThrough .mjx-mrow').should('contain.text', '(9,−9)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(9,−9)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(14,−3)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(9,−9)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(14,−3)'); + + + + cy.log('cannot change dimnension through copied head') + cy.get('#\\/miv2t textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 0,1,2,3{enter}", { force: true }); + cy.get('#\\/vThrough .mjx-mrow').should('contain.text', '(0,1)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(0,1)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(5,7)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(0,1)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(5,7)'); + + + cy.log('cannot change dimnension through copied tail') + cy.get('#\\/miv2e textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 2, 4, 6, 8{enter}", { force: true }); + cy.get('#\\/vEndpoint .mjx-mrow').should('contain.text', '(2,4)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(7,11)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(5,7)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(7,11)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(5,7)'); + + + cy.log('cannot change dimnension through copied displacement') + cy.get('#\\/miv2d textarea').type("{ctrl+home}{shift+end}{backspace}\\langle -8, -6, =4, -2{enter}", { force: true }); + cy.get('#\\/vDirection .mjx-mrow').should('contain.text', '(−8,−6)'); + + cy.get('#\\/vThrough .mjx-mrow').eq(0).should('have.text', '(−6,−2)'); + cy.get('#\\/vEndpoint .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/vDirection .mjx-mrow').eq(0).should('have.text', '(−8,−6)'); + cy.get('#\\/v2Through .mjx-mrow').eq(0).should('have.text', '(−6,−2)'); + cy.get('#\\/v2Endpoint .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/v2Direction .mjx-mrow').eq(0).should('have.text', '(−8,−6)'); + + + }) + }); \ No newline at end of file diff --git a/cypress/e2e/DoenetML/tagSpecific/vector.cy.js b/cypress/e2e/DoenetML/tagSpecific/vector.cy.js index 6f03da0874..9bb9bea7f2 100644 --- a/cypress/e2e/DoenetML/tagSpecific/vector.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/vector.cy.js @@ -13342,5 +13342,306 @@ describe('Vector Tag Tests', function () { }) }); + it('change vector by binding to values', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + + + +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ + `}, "*"); + }); + + // to wait for page to load + cy.get('#\\/v .mjx-mrow').should('contain.text', '(1,0)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(1,0)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(1,0)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(1,0)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(0,0)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(1,0)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(1,0)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(0,0)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(1,0)'); + + cy.log('change head using alt vector') + cy.get('#\\/mivh textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 6,9{enter}", { force: true }); + + cy.get('#\\/vHead .mjx-mrow').should('contain.text', '(6,9)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(0,0)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(0,0)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(6,9)'); + + + cy.log('change tail using alt vector') + cy.get('#\\/mivt textarea').type("{ctrl+home}{shift+end}{backspace}\\langle -3,7{enter}", { force: true }); + cy.get('#\\/vTail .mjx-mrow').should('contain.text', '(−3,7)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(3,16)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(6,9)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(3,16)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(6,9)'); + + cy.log('change displacement using alt vector') + cy.get('#\\/mivd textarea').type("{ctrl+home}{shift+end}{backspace}\\langle -4,1{enter}", { force: true }); + cy.get('#\\/vDisplacement .mjx-mrow').should('contain.text', '(−4,1)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(−4,1)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(−4,1)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(−7,8)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(−4,1)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(−7,8)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(−4,1)'); + + + cy.log('cannot change dimnension through displacement') + cy.get('#\\/mivd textarea').type("{ctrl+home}{shift+end}{backspace}(9,8,7{enter}", { force: true }); + cy.get('#\\/vDisplacement .mjx-mrow').should('contain.text', '(9,8)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(9,8)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(9,8)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(6,15)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(9,8)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(6,15)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(−3,7)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(9,8)'); + + + cy.log('cannot change dimnension through tail') + cy.get('#\\/mivt textarea').type("{ctrl+home}{shift+end}{backspace}(-5,-6,-7{enter}", { force: true }); + cy.get('#\\/vTail .mjx-mrow').should('contain.text', '(−5,−6)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(9,8)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(9,8)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(4,2)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(9,8)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(4,2)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(9,8)'); + + + cy.log('cannot change dimnension through head') + cy.get('#\\/mivh textarea').type("{ctrl+home}{shift+end}{backspace}(9,-9,7{enter}", { force: true }); + cy.get('#\\/vHead .mjx-mrow').should('contain.text', '(9,−9)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(14,−3)'); `` + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(14,−3)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(9,−9)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(14,−3)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(9,−9)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(14,−3)'); + + + + cy.log('cannot change dimnension through copied head') + cy.get('#\\/miv2h textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 0,1,2,3{enter}", { force: true }); + cy.get('#\\/vHead .mjx-mrow').should('contain.text', '(0,1)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(5,7)'); `` + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(5,7)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(0,1)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(5,7)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(0,1)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(−5,−6)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(5,7)'); + + + cy.log('cannot change dimnension through copied tail') + cy.get('#\\/miv2t textarea').type("{ctrl+home}{shift+end}{backspace}\\langle 2, 4, 6, 8{enter}", { force: true }); + cy.get('#\\/vTail .mjx-mrow').should('contain.text', '(2,4)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(5,7)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(5,7)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(7,11)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(5,7)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(7,11)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(5,7)'); + + + cy.log('cannot change dimnension through copied displacement') + cy.get('#\\/miv2d textarea').type("{ctrl+home}{shift+end}{backspace}\\langle -8, -6, =4, -2{enter}", { force: true }); + cy.get('#\\/vDisplacement .mjx-mrow').should('contain.text', '(−8,−6)'); + + cy.get('#\\/v .mjx-mrow').eq(0).should('have.text', '(−8,−6)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '(−8,−6)'); + cy.get('#\\/vHead .mjx-mrow').eq(0).should('have.text', '(−6,−2)'); + cy.get('#\\/vTail .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/vDisplacement .mjx-mrow').eq(0).should('have.text', '(−8,−6)'); + cy.get('#\\/v2Head .mjx-mrow').eq(0).should('have.text', '(−6,−2)'); + cy.get('#\\/v2Tail .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/v2Displacement .mjx-mrow').eq(0).should('have.text', '(−8,−6)'); + + + }) + + it('display with angle brackets', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + +

+ (1,2) + (1,2) + (1,2) +

+ +

+ + + +

+ +

+ + + +

+ +

+ + + +

+ + + + `}, "*"); + }); + + // to wait for page to load + cy.get('#\\/v1 .mjx-mrow').should('contain.text', '(1,2)'); + + cy.get('#\\/v1 .mjx-mrow').eq(0).should('have.text', '(1,2)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + cy.get('#\\/v3 .mjx-mrow').eq(0).should('have.text', '(1,2)'); + + cy.get('#\\/v1a .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + cy.get('#\\/v2a .mjx-mrow').eq(0).should('have.text', '(1,2)'); + cy.get('#\\/v3a .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + + cy.get('#\\/v1d .mjx-mrow').eq(0).should('have.text', '(1,2)'); + cy.get('#\\/v2d .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + cy.get('#\\/v3d .mjx-mrow').eq(0).should('have.text', '(1,2)'); + + cy.get('#\\/v1ad .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + cy.get('#\\/v2ad .mjx-mrow').eq(0).should('have.text', '(1,2)'); + cy.get('#\\/v3ad .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + + cy.get('#\\/bi').click(); + + cy.get('#\\/v3 .mjx-mrow').should('contain.text', '⟨1,2⟩'); + + + cy.get('#\\/v1 .mjx-mrow').eq(0).should('have.text', '(1,2)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + cy.get('#\\/v3 .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + + cy.get('#\\/v1a .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + cy.get('#\\/v2a .mjx-mrow').eq(0).should('have.text', '(1,2)'); + cy.get('#\\/v3a .mjx-mrow').eq(0).should('have.text', '(1,2)'); + + cy.get('#\\/v1d .mjx-mrow').eq(0).should('have.text', '(1,2)'); + cy.get('#\\/v2d .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + cy.get('#\\/v3d .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + + cy.get('#\\/v1ad .mjx-mrow').eq(0).should('have.text', '⟨1,2⟩'); + cy.get('#\\/v2ad .mjx-mrow').eq(0).should('have.text', '(1,2)'); + cy.get('#\\/v3ad .mjx-mrow').eq(0).should('have.text', '(1,2)'); + + + cy.window().then(async (win) => { + + win.callAction1({ + actionName: "moveVector", + componentName: "/v1", + args: { + headcoords: [2, 4], + } + }) + + win.callAction1({ + actionName: "moveVector", + componentName: "/v2", + args: { + headcoords: [3, 5], + } + }) + + win.callAction1({ + actionName: "moveVector", + componentName: "/v3", + args: { + headcoords: [4, 6], + } + }) + + }) + + + + cy.get('#\\/v3 .mjx-mrow').should('contain.text', '⟨4,6⟩'); + + + cy.get('#\\/v1 .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/v2 .mjx-mrow').eq(0).should('have.text', '⟨3,5⟩'); + cy.get('#\\/v3 .mjx-mrow').eq(0).should('have.text', '⟨4,6⟩'); + + cy.get('#\\/v1a .mjx-mrow').eq(0).should('have.text', '⟨2,4⟩'); + cy.get('#\\/v2a .mjx-mrow').eq(0).should('have.text', '(3,5)'); + cy.get('#\\/v3a .mjx-mrow').eq(0).should('have.text', '(4,6)'); + + cy.get('#\\/v1d .mjx-mrow').eq(0).should('have.text', '(2,4)'); + cy.get('#\\/v2d .mjx-mrow').eq(0).should('have.text', '⟨3,5⟩'); + cy.get('#\\/v3d .mjx-mrow').eq(0).should('have.text', '⟨4,6⟩'); + + cy.get('#\\/v1ad .mjx-mrow').eq(0).should('have.text', '⟨2,4⟩'); + cy.get('#\\/v2ad .mjx-mrow').eq(0).should('have.text', '(3,5)'); + cy.get('#\\/v3ad .mjx-mrow').eq(0).should('have.text', '(4,6)'); + + }) + }); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c7eec56424..3799be65a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "json-stringify-deterministic": "^1.0.1", "lodash.debounce": "^4.0.8", "lorem-ipsum": "^2.0.4", - "math-expressions": "^2.0.0-alpha52", + "math-expressions": "^2.0.0-alpha54", "nanoid": "^3.1.31", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.3", @@ -1024,6 +1024,22 @@ "version": "0.3.0", "license": "MIT" }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz", + "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.3.3", "devOptional": true, @@ -4912,9 +4928,10 @@ }, "node_modules/esbuild": { "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz", + "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", "dev": true, "hasInstallScript": true, - "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -4945,6 +4962,326 @@ "esbuild-windows-arm64": "0.14.54" } }, + "node_modules/esbuild-android-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz", + "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz", + "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz", + "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz", + "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz", + "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz", + "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz", + "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz", + "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz", + "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz", + "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz", + "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz", + "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz", + "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz", + "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz", + "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz", + "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz", + "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz", + "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz", + "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz", + "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/escalade": { "version": "3.1.1", "license": "MIT", @@ -7977,8 +8314,9 @@ "license": "Apache-2.0" }, "node_modules/math-expressions": { - "version": "2.0.0-alpha52", - "license": "(GPL-3.0 OR Apache-2.0)", + "version": "2.0.0-alpha54", + "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha54.tgz", + "integrity": "sha512-Q7Z4sO8vFzd9b9cd/yc6jO3zUN0PWn5pAixpM7Ukqow75XN1VjrWP1E8LTMgjtUGc7nwdwqNDOqX4/QpkD+PGA==", "dependencies": { "@babel/cli": "^7.0.0", "babel-upgrade": "^1.0.1", @@ -12871,6 +13209,13 @@ "@emotion/weak-memoize": { "version": "0.3.0" }, + "@esbuild/linux-loong64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz", + "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==", + "dev": true, + "optional": true + }, "@eslint/eslintrc": { "version": "1.3.3", "devOptional": true, @@ -15486,6 +15831,8 @@ }, "esbuild": { "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz", + "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", "dev": true, "requires": { "@esbuild/linux-loong64": "0.14.54", @@ -15511,6 +15858,146 @@ "esbuild-windows-arm64": "0.14.54" } }, + "esbuild-android-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz", + "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz", + "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz", + "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz", + "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz", + "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz", + "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz", + "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz", + "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz", + "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz", + "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz", + "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz", + "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz", + "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz", + "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz", + "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz", + "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz", + "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz", + "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz", + "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz", + "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==", + "dev": true, + "optional": true + }, "escalade": { "version": "3.1.1" }, @@ -17473,7 +17960,9 @@ "dev": true }, "math-expressions": { - "version": "2.0.0-alpha52", + "version": "2.0.0-alpha54", + "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha54.tgz", + "integrity": "sha512-Q7Z4sO8vFzd9b9cd/yc6jO3zUN0PWn5pAixpM7Ukqow75XN1VjrWP1E8LTMgjtUGc7nwdwqNDOqX4/QpkD+PGA==", "requires": { "@babel/cli": "^7.0.0", "babel-upgrade": "^1.0.1", diff --git a/package.json b/package.json index 06115b1263..2d8f7f00bd 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "json-stringify-deterministic": "^1.0.1", "lodash.debounce": "^4.0.8", "lorem-ipsum": "^2.0.4", - "math-expressions": "^2.0.0-alpha52", + "math-expressions": "^2.0.0-alpha54", "nanoid": "^3.1.31", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.3", diff --git a/src/Core/Core.js b/src/Core/Core.js index 9bdefb0a4f..fadbe3f8c8 100644 --- a/src/Core/Core.js +++ b/src/Core/Core.js @@ -4799,6 +4799,21 @@ export default class Core { args.usedDefaultByKey = usedDefaultByKey; args.dependencyNamesByKey = stateVarObj.dependencyNames.namesByKey; + + // only include array keys that exist + let newDesiredStateVariableValues = {}; + for (let vName in args.desiredStateVariableValues) { + newDesiredStateVariableValues[vName] = {} + for (let key in args.desiredStateVariableValues[vName]) { + if (args.arrayKeys.includes(key)) { + newDesiredStateVariableValues[vName][key] = args.desiredStateVariableValues[vName][key]; + + } + } + } + args.desiredStateVariableValues = newDesiredStateVariableValues; + + // args.arraySize = stateVarObj.arraySize; // let arrayKeysToInvert = []; diff --git a/src/Core/components/DiscreteSimulationResultList.js b/src/Core/components/DiscreteSimulationResultList.js index 3ac6309aba..7f231feecb 100644 --- a/src/Core/components/DiscreteSimulationResultList.js +++ b/src/Core/components/DiscreteSimulationResultList.js @@ -210,7 +210,7 @@ export default class DiscreteSimulationResultList extends BlockComponent { if (dependencyValues.allIterates.length > 0 && Array.isArray(dependencyValues.allIterates[0].tree) && - ["vector", "tuple"].includes(dependencyValues.allIterates[0].tree[0]) + ["vector", "altvector", "tuple"].includes(dependencyValues.allIterates[0].tree[0]) ) { nComponents = dependencyValues.allIterates[0].tree.length - 1; haveVector = true; diff --git a/src/Core/components/DiscreteSimulationResultPolyline.js b/src/Core/components/DiscreteSimulationResultPolyline.js index 35d0dd13ee..9e02f68cce 100644 --- a/src/Core/components/DiscreteSimulationResultPolyline.js +++ b/src/Core/components/DiscreteSimulationResultPolyline.js @@ -107,7 +107,7 @@ export default class DiscreteSimulationResultPolyline extends GraphicalComponent setValue: { allIterates: dependencyValues.allIteratesSub.filter(x => Number.isFinite(x.tree) || - (Array.isArray(x.tree) && ["tuple", "vector"].includes(x.tree[0]) && x.tree.slice(1).every(Number.isFinite)) + (Array.isArray(x.tree) && ["tuple", "vector", "altvector"].includes(x.tree[0]) && x.tree.slice(1).every(Number.isFinite)) ) } } diff --git a/src/Core/components/Evaluate.js b/src/Core/components/Evaluate.js index a63f9f3269..3d89aec4fd 100644 --- a/src/Core/components/Evaluate.js +++ b/src/Core/components/Evaluate.js @@ -351,7 +351,7 @@ export default class Evaluate extends MathComponent { // if have a single input, check if it is a vector if (input.length === 1) { let inputTree = input[0].tree; - if (Array.isArray(inputTree) && ["vector", "tuple"].includes(inputTree[0])) { + if (Array.isArray(inputTree) && ["vector", "altvector", "tuple"].includes(inputTree[0])) { input = inputTree.slice(1).map(x => me.fromAst(x)); } } diff --git a/src/Core/components/Function.js b/src/Core/components/Function.js index e9abc0881e..ce9c7b4278 100644 --- a/src/Core/components/Function.js +++ b/src/Core/components/Function.js @@ -605,7 +605,7 @@ export default class Function extends InlineComponent { } else if (dependencyValues.mathChild.length > 0) { let formula = dependencyValues.mathChild[0].stateValues.value; let formulaIsVectorValued = Array.isArray(formula.tree) && - ["tuple", "vector"].includes(formula.tree[0]); + ["tuple", "vector", "altvector"].includes(formula.tree[0]); let nOutputs = 1; if (formulaIsVectorValued) { @@ -2365,11 +2365,11 @@ export default class Function extends InlineComponent { } } if (varName === "minimumLocations") { - // if propIndex has additional entries, ignore them + // if propIndex has additional entries, ignore them return "minimumLocation" + propIndex[0]; } if (varName === "minimumValues") { - // if propIndex has additional entries, ignore them + // if propIndex has additional entries, ignore them return "minimumValue" + propIndex[0]; } if (varName.slice(0, 7) === "minimum") { @@ -2980,11 +2980,11 @@ export default class Function extends InlineComponent { } } if (varName === "maximumLocations") { - // if propIndex has additional entries, ignore them + // if propIndex has additional entries, ignore them return "maximumLocation" + propIndex[0]; } if (varName === "maximumValues") { - // if propIndex has additional entries, ignore them + // if propIndex has additional entries, ignore them return "maximumValue" + propIndex[0]; } if (varName.slice(0, 7) === "maximum") { @@ -3184,11 +3184,11 @@ export default class Function extends InlineComponent { } } if (varName === "extremumLocations") { - // if propIndex has additional entries, ignore them + // if propIndex has additional entries, ignore them return "extremumLocation" + propIndex[0]; } if (varName === "extremumValues") { - // if propIndex has additional entries, ignore them + // if propIndex has additional entries, ignore them return "extremumValue" + propIndex[0]; } if (varName.slice(0, 8) === "extremum") { diff --git a/src/Core/components/FunctionIterates.js b/src/Core/components/FunctionIterates.js index 1aeb77194a..a0fe3538dc 100644 --- a/src/Core/components/FunctionIterates.js +++ b/src/Core/components/FunctionIterates.js @@ -117,7 +117,7 @@ export default class FunctionIterates extends InlineComponent { !functionComp || dependencyValues.nDimensions === 0 || !(dependencyValues.nDimensions === 1 || Array.isArray(initialValue.tree) - && ["vector", "tuple"].includes(initialValue.tree[0]) + && ["vector", "altvector", "tuple"].includes(initialValue.tree[0]) && initialValue.tree.length === dependencyValues.nDimensions + 1 ) ) { diff --git a/src/Core/components/Math.js b/src/Core/components/Math.js index 68c7a3eb44..0c6390fcfb 100644 --- a/src/Core/components/Math.js +++ b/src/Core/components/Math.js @@ -1422,7 +1422,7 @@ export default class MathComponent extends InlineComponent { if (nMathChildren === 0 || !Array.isArray(expressionWithCodesTree) || - !["tuple", "vector"].includes(expressionWithCodesTree[0]) + !["tuple", "vector", "altvector"].includes(expressionWithCodesTree[0]) ) { return { setValue: { mathChildrenByVectorComponent: null } }; } @@ -1478,7 +1478,7 @@ export default class MathComponent extends InlineComponent { let tree = dependencyValues.value.tree; if (Array.isArray(tree)) { - if (["vector", "tuple", "list"].includes(tree[0])) { + if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { nDimensions = tree.length - 1; } else if (tree[0] === "matrix") { let size = tree[1].slice(1); @@ -1488,7 +1488,7 @@ export default class MathComponent extends InlineComponent { } else if (size[1] === 1) { nDimensions = size[0]; } - } else if ((tree[1][0] === "vector" || tree[1][0] === "tuple") + } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { nDimensions = tree[1].length - 1; @@ -1544,7 +1544,7 @@ export default class MathComponent extends InlineComponent { let vector = {}; if (Array.isArray(tree)) { - if (["vector", "tuple", "list"].includes(tree[0])) { + if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { for (let ind = 0; ind < arraySize[0]; ind++) { vector[ind] = me.fromAst(tree[ind + 1]); } @@ -1562,7 +1562,7 @@ export default class MathComponent extends InlineComponent { } createdVector = true; } - } else if ((tree[1][0] === "vector" || tree[1][0] === "tuple") + } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { for (let ind = 0; ind < arraySize[0]; ind++) { @@ -1598,7 +1598,7 @@ export default class MathComponent extends InlineComponent { let desiredValue; let tree = globalDependencyValues.value.tree; if (Array.isArray(tree)) { - if (["vector", "tuple", "list"].includes(tree[0])) { + if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { desiredValue = me.fromAst([tree[0], ...workspace.desiredVector.map(x => x.tree)]) } else if (tree[0] === "matrix") { let size = tree[1].slice(1); @@ -1616,7 +1616,7 @@ export default class MathComponent extends InlineComponent { } desiredValue = me.fromAst(["matrix", tree[1], desiredMatrixVals]) } - } else if ((tree[1][0] === "vector" || tree[1][0] === "tuple") + } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { desiredValue = [tree[0], [tree[1][0], ...workspace.desiredVector.map(x => x.tree)]] @@ -1677,11 +1677,11 @@ export default class MathComponent extends InlineComponent { let tree = dependencyValues.value.tree; if (Array.isArray(tree)) { - if (["vector", "tuple", "list"].includes(tree[0])) { + if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { matrixSize = [tree.length - 1, 1]; } else if (tree[0] === "matrix") { matrixSize = tree[1].slice(1); - } else if ((tree[1][0] === "vector" || tree[1][0] === "tuple") + } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { matrixSize = [1, tree[1].length - 1]; @@ -1886,7 +1886,7 @@ export default class MathComponent extends InlineComponent { let matrix = {}; if (Array.isArray(tree)) { - if (["vector", "tuple", "list"].includes(tree[0])) { + if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { for (let ind = 0; ind < arraySize[0]; ind++) { matrix[ind + ",0"] = me.fromAst(tree[ind + 1]); } @@ -1899,7 +1899,7 @@ export default class MathComponent extends InlineComponent { } } createdMatrix = true; - } else if ((tree[1][0] === "vector" || tree[1][0] === "tuple") + } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { for (let ind = 0; ind < arraySize[1]; ind++) { @@ -1937,7 +1937,7 @@ export default class MathComponent extends InlineComponent { let desiredValue; let tree = globalDependencyValues.value.tree; if (Array.isArray(tree)) { - if (["vector", "tuple", "list"].includes(tree[0])) { + if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { desiredValue = [tree[0]] for (let ind = 0; ind < arraySize[0]; ind++) { desiredValue.push(workspace.desiredMatrix[ind + ",0"].tree) @@ -1954,7 +1954,7 @@ export default class MathComponent extends InlineComponent { desiredMatrixVals.push(row); } desiredValue = me.fromAst(["matrix", tree[1], desiredMatrixVals]) - } else if ((tree[1][0] === "vector" || tree[1][0] === "tuple") + } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { @@ -2553,7 +2553,7 @@ function checkForLinearExpression(tree, variables, inverseTree, constants = [], let operands = tree.slice(1); // for container, check if at least one component is a linear expression - if (operator === "tuple" || operator === "vector" || operator === "list") { + if (operator === "tuple" || operator === "vector" || operator === "altvector" || operator === "list") { let result = { mappings: {}, template: [operator] };//, modifiableStrings: {}}; let numLinear = 0; @@ -2809,7 +2809,7 @@ async function invertMath({ desiredStateVariableValues, dependencyValues, } } - if (["vector", "tuple", "list"].includes(newExpressionWithCodes.tree[0]) && + if (["vector", "altvector", "tuple", "list"].includes(newExpressionWithCodes.tree[0]) && !newExpressionWithCodes.tree.slice(1).every(mathComponentContainsCode) ) { diff --git a/src/Core/components/MatrixInput.js b/src/Core/components/MatrixInput.js index 7aeafe1d7f..9c93d49bce 100644 --- a/src/Core/components/MatrixInput.js +++ b/src/Core/components/MatrixInput.js @@ -338,7 +338,7 @@ export class MatrixInput extends Input { let operator = originalTree[0]; if (operator === "matrix") { numRows = originalTree[1][1]; - } else if (operator === "vector" || operator == "tuple") { + } else if (operator === "vector" || operator === "altvector" || operator == "tuple") { numRows = originalTree.length - 1; } @@ -366,7 +366,7 @@ export class MatrixInput extends Input { let originalTree = dependencyValues.valueOriginal.tree; let defaultEntryTree = (await stateValues.defaultEntry).tree; if (await stateValues.numColumns === 1 && Array.isArray(originalTree) - && (originalTree[0] === "vector" || originalTree[0] === "tuple") + && (originalTree[0] === "vector" || originalTree[0] === "altvector" || originalTree[0] === "tuple") ) { // original value was a vector // so we keep it a vector @@ -483,7 +483,7 @@ export class MatrixInput extends Input { if (operator === "matrix") { numColumns = originalTree[1][2]; } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { numColumns = originalTree[1].length - 1; @@ -514,7 +514,7 @@ export class MatrixInput extends Input { let operator = originalTree[0]; if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { @@ -627,7 +627,7 @@ export class MatrixInput extends Input { return { setValue: { accumulatedComponents } } - } else if (operator === "vector" || operator === "tuple") { + } else if (operator === "vector" || operator === "altvector" || operator === "tuple") { // treat vector/tuple as first column in matrix for (let [rowInd, comp] of originalTree.slice(1).entries()) { @@ -641,7 +641,7 @@ export class MatrixInput extends Input { return { setValue: { accumulatedComponents } } } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { // treat transpose of vector/tuple as first row in matrix @@ -796,7 +796,7 @@ export class MatrixInput extends Input { return { setValue: { componentValues } } - } else if (operator === "vector" || operator === "tuple") { + } else if (operator === "vector" || operator === "altvector" || operator === "tuple") { // treat vector/tuple as first column in matrix @@ -830,7 +830,7 @@ export class MatrixInput extends Input { return { setValue: { componentValues } } } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { @@ -921,12 +921,12 @@ export class MatrixInput extends Input { if (Array.isArray(originalTree)) { let operator = originalTree[0]; - if (operator === "vector" || operator === "tuple") { + if (operator === "vector" || operator === "altvector" || operator === "tuple") { originalIsColumnVector = true; } else if (operator === "matrix") { originalIsMatrix = true; } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { originalIsRowVector = true; @@ -1194,7 +1194,7 @@ export class MatrixInput extends Input { return { setValue: { componentImmediateValues } } - } else if (operator === "vector" || operator === "tuple") { + } else if (operator === "vector" || operator === "altvector" || operator === "tuple") { // treat vector/tuple as first column in matrix @@ -1228,7 +1228,7 @@ export class MatrixInput extends Input { return { setValue: { componentImmediateValues } } } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { @@ -1319,12 +1319,12 @@ export class MatrixInput extends Input { if (Array.isArray(originalTree)) { let operator = originalTree[0]; - if (operator === "vector" || operator === "tuple") { + if (operator === "vector" || operator === "altvector" || operator === "tuple") { originalIsColumnVector = true; } else if (operator === "matrix") { originalIsMatrix = true; } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { originalIsRowVector = true; @@ -1601,7 +1601,7 @@ export class MatrixInput extends Input { if (Array.isArray(originalTree)) { let operator = originalTree[0]; - if (operator === "vector" || operator === "tuple") { + if (operator === "vector" || operator === "altvector" || operator === "tuple") { // if original value was a vector, then keep it as a vector let desiredValue = me.fromAst([operator, ...desiredTree[2].slice(1).map(x => x[1])]) return { @@ -1619,7 +1619,7 @@ export class MatrixInput extends Input { let operator = originalTree[0]; if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { // if original value was the transpose of a vector, @@ -1716,7 +1716,7 @@ export class MatrixInput extends Input { if (Array.isArray(originalTree)) { let operator = originalTree[0]; - if (operator === "vector" || operator === "tuple") { + if (operator === "vector" || operator === "altvector" || operator === "tuple") { // if original immediateValue was a vector, then keep it as a vector let desiredValue = me.fromAst([operator, ...desiredTree[2].slice(1).map(x => x[1])]) return { @@ -1734,7 +1734,7 @@ export class MatrixInput extends Input { let operator = originalTree[0]; if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "tuple") + && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { // if original immediateValue was the transpose of a vector, diff --git a/src/Core/components/Point.js b/src/Core/components/Point.js index d5ebbb9964..488a151ea9 100644 --- a/src/Core/components/Point.js +++ b/src/Core/components/Point.js @@ -442,7 +442,7 @@ export default class Point extends GraphicalComponent { if (basedOnCoords) { let coordsTree = coords.tree; - if (Array.isArray(coordsTree) && ["tuple", "vector"].includes(coordsTree[0])) { + if (Array.isArray(coordsTree) && ["tuple", "vector", "altvector"].includes(coordsTree[0])) { nDimensions = Math.max(coordsTree.length - 1, nDimensions); } else { nDimensions = Math.max(1, nDimensions); @@ -602,7 +602,7 @@ export default class Point extends GraphicalComponent { if (basedOnCoords) { let coordsTree = coords.tree; - if (Array.isArray(coordsTree) && ["tuple", "vector"].includes(coordsTree[0])) { + if (Array.isArray(coordsTree) && ["tuple", "vector", "altvector"].includes(coordsTree[0])) { for (let arrayKey of arrayKeys) { let ind = Number(arrayKey); if (ind >= 0 || ind < coordsTree.length - 1) { @@ -952,7 +952,7 @@ export default class Point extends GraphicalComponent { let coordsTree = desiredStateVariableValues.coords.tree; - if (!(Array.isArray(coordsTree) && ["tuple", "vector"].includes(coordsTree[0]))) { + if (!(Array.isArray(coordsTree) && ["tuple", "vector", "altvector"].includes(coordsTree[0]))) { desiredXValues[0] = desiredStateVariableValues.coords; } else { for (let i = 0; i < coordsTree.length - 1; i++) { diff --git a/src/Core/components/Ray.js b/src/Core/components/Ray.js index d4f1ecde5e..33685e9151 100644 --- a/src/Core/components/Ray.js +++ b/src/Core/components/Ray.js @@ -326,7 +326,7 @@ export default class Ray extends GraphicalComponent { nDimDirection = dependencyValues.directionAttr.stateValues.nDimensions; } else if (dependencyValues.directionShadow) { let directionTree = dependencyValues.directionShadow.tree; - if (Array.isArray(directionTree) && ["tuple", "vector"].includes(directionTree[0])) { + if (Array.isArray(directionTree) && ["tuple", "vector", "altvector"].includes(directionTree[0])) { nDimDirection = directionTree.length - 1; } else { nDimDirection = 2; @@ -410,7 +410,7 @@ export default class Ray extends GraphicalComponent { nDimThrough = dependencyValues.throughAttr.stateValues.nDimensions; } else if (dependencyValues.throughShadow) { let throughTree = dependencyValues.throughShadow.tree; - if (Array.isArray(throughTree) && ["tuple", "vector"].includes(throughTree[0])) { + if (Array.isArray(throughTree) && ["tuple", "vector", "altvector"].includes(throughTree[0])) { nDimThrough = throughTree.length - 1; } else { nDimThrough = 2; @@ -494,7 +494,7 @@ export default class Ray extends GraphicalComponent { nDimEndpoint = dependencyValues.endpointAttr.stateValues.nDimensions; } else if (dependencyValues.endpointShadow) { let endpointTree = dependencyValues.endpointShadow.tree; - if (Array.isArray(endpointTree) && ["tuple", "vector"].includes(endpointTree[0])) { + if (Array.isArray(endpointTree) && ["tuple", "vector", "altvector"].includes(endpointTree[0])) { nDimEndpoint = endpointTree.length - 1; } else { nDimEndpoint = 2; diff --git a/src/Core/components/Spreadsheet.js b/src/Core/components/Spreadsheet.js index bb3e068cba..1dfca5ccc5 100644 --- a/src/Core/components/Spreadsheet.js +++ b/src/Core/components/Spreadsheet.js @@ -1171,7 +1171,7 @@ export default class Spreadsheet extends BlockComponent { } if (Array.isArray(cellME.tree) && ( - cellME.tree[0] === "tuple" || cellME.tree[0] === "vector" + cellME.tree[0] === "tuple" || cellME.tree[0] === "vector" || cellME.tree[0] === "altvector" )) { pointsInCells[arrayKey] = cellME; } else { diff --git a/src/Core/components/Vector.js b/src/Core/components/Vector.js index 97dd40013e..9d9dbc4069 100644 --- a/src/Core/components/Vector.js +++ b/src/Core/components/Vector.js @@ -87,6 +87,13 @@ export default class Vector extends GraphicalComponent { public: true, }; + attributes.displayWithAngleBrackets = { + createComponentOfType: "boolean", + createStateVariable: "displayWithAngleBrackets", + defaultValue: false, + public: true, + }; + return attributes; } @@ -691,7 +698,7 @@ export default class Vector extends GraphicalComponent { // since based on displacement and no source of displacement // we must have a displacement shadow let displacementTree = dependencyValues.displacementShadow.tree; - if (Array.isArray(displacementTree) && ["tuple", "vector"].includes(displacementTree[0])) { + if (Array.isArray(displacementTree) && ["tuple", "vector", "altvector"].includes(displacementTree[0])) { nDimDisplacement = displacementTree.length - 1; } else { nDimDisplacement = 1; @@ -775,7 +782,7 @@ export default class Vector extends GraphicalComponent { nDimHead = dependencyValues.headAttr.stateValues.nDimensions; } else if (dependencyValues.headShadow) { let headTree = dependencyValues.headShadow.tree; - if (Array.isArray(headTree) && ["tuple", "vector"].includes(headTree[0])) { + if (Array.isArray(headTree) && ["tuple", "vector", "altvector"].includes(headTree[0])) { nDimHead = headTree.length - 1; } else { nDimHead = 2; @@ -859,7 +866,7 @@ export default class Vector extends GraphicalComponent { nDimTail = dependencyValues.tailAttr.stateValues.nDimensions; } else if (dependencyValues.tailShadow) { let tailTree = dependencyValues.tailShadow.tree; - if (Array.isArray(tailTree) && ["tuple", "vector"].includes(tailTree[0])) { + if (Array.isArray(tailTree) && ["tuple", "vector", "altvector"].includes(tailTree[0])) { nDimTail = tailTree.length - 1; } else { nDimTail = 2; @@ -974,7 +981,7 @@ export default class Vector extends GraphicalComponent { public: true, shadowingInstructions: { createComponentOfType: "math", - attributesToShadow: ["displayDigits", "displayDecimals", "displaySmallAsZero", "padZeros"], + attributesToShadow: ["displayDigits", "displayDecimals", "displaySmallAsZero", "padZeros", "displayWithAngleBrackets"], returnWrappingComponents(prefix) { if (prefix === "x") { return []; @@ -1131,7 +1138,7 @@ export default class Vector extends GraphicalComponent { // since based on displacement and no source of displacement // we must have a displacement shadow let displacementTree = globalDependencyValues.displacementShadow.tree; - if (Array.isArray(displacementTree) && ["tuple", "vector"].includes(displacementTree[0])) { + if (Array.isArray(displacementTree) && ["tuple", "vector", "altvector"].includes(displacementTree[0])) { displacement[arrayKey] = globalDependencyValues.displacementShadow.get_component(Number(arrayKey)); } else { displacement[arrayKey] = globalDependencyValues.displacementShadow; @@ -1841,6 +1848,10 @@ export default class Vector extends GraphicalComponent { displacement: { dependencyType: "stateVariable", variableName: "displacement" + }, + displayWithAngleBrackets: { + dependencyType: "stateVariable", + variableName: "displayWithAngleBrackets" } }), definition({ dependencyValues }) { @@ -1853,7 +1864,8 @@ export default class Vector extends GraphicalComponent { } } if (coordsAst.length > 1) { - coordsAst = ["vector", ...coordsAst]; + let operator = dependencyValues.displayWithAngleBrackets ? "altvector" : "vector"; + coordsAst = [operator, ...coordsAst]; } else if (coordsAst.length === 1) { coordsAst = coordsAst[0]; } else { @@ -1867,7 +1879,7 @@ export default class Vector extends GraphicalComponent { let coordsAst = desiredStateVariableValues.displacementCoords.tree; let newDisplacement; - if (Array.isArray(coordsAst) && (coordsAst[0] === "vector" || coordsAst[0] === "tuple")) { + if (Array.isArray(coordsAst) && (coordsAst[0] === "vector" || coordsAst[0] === "altvector" || coordsAst[0] === "tuple")) { newDisplacement = coordsAst.slice(1).map(x => me.fromAst(x)); } else { newDisplacement = [desiredStateVariableValues.displacementCoords]; diff --git a/src/Core/utils/checkEquality.js b/src/Core/utils/checkEquality.js index 773126b57b..62577b8804 100644 --- a/src/Core/utils/checkEquality.js +++ b/src/Core/utils/checkEquality.js @@ -304,7 +304,7 @@ export default function checkEquality({ // a list of length 1 // make object1 act like a list of the one element object1 = [object1.tree]; - } else if (object1_operator === "vector") { + } else if (object1_operator === "vector" || object1_operator === "altvector") { // change object1 to array of elements object1 = object1.tree.slice(1); @@ -313,7 +313,7 @@ export default function checkEquality({ || object2_operator === "set" ) { return { fraction_equal: 0 }; - } else if (object2_operator === "tuple" || object2_operator === "vector") { + } else if (object2_operator === "tuple" || object2_operator === "vector" || object2_operator === "altvector") { // since we can convert tuple to vector // change object2 to array of selements object2 = object2.tree.slice(1); @@ -322,7 +322,7 @@ export default function checkEquality({ // make object2 array of the one element object2 = [object2.tree]; } - } else if (object2_operator === "vector") { + } else if (object2_operator === "vector" || object2_operator === "altvector") { // change object2 to array of elements object2 = object2.tree.slice(1); diff --git a/src/Core/utils/function.js b/src/Core/utils/function.js index aa4dc318c6..fea6f42ddb 100644 --- a/src/Core/utils/function.js +++ b/src/Core/utils/function.js @@ -60,7 +60,7 @@ export function returnNumericalFunctionFromFormula({ formula, nInputs, variables component = Number(component); let formulaIsVectorValued = Array.isArray(formula.tree) && - ["tuple", "vector"].includes(formula.tree[0]); + ["tuple", "vector", "altvector"].includes(formula.tree[0]); if (formulaIsVectorValued) { try { @@ -105,8 +105,8 @@ export function returnNumericalFunctionFromFormula({ formula, nInputs, variables } return function (x, overrideDomain = false) { - if(overrideDomain) { - if(isNaN(x)) { + if (overrideDomain) { + if (isNaN(x)) { return NaN; } } else if (!(x >= minx) || !(x <= maxx) || (openMin && x === minx) || (openMax && x === maxx)) { @@ -146,7 +146,7 @@ export function returnSymbolicFunctionFromFormula(dependencyValues, arrayKey) { let formula = dependencyValues.formula; let formulaIsVectorValued = Array.isArray(formula.tree) && - ["tuple", "vector"].includes(formula.tree[0]); + ["tuple", "vector", "altvector"].includes(formula.tree[0]); if (formulaIsVectorValued) { try { @@ -298,8 +298,8 @@ export function returnInterpolatedFunction({ xs, coeffs, interpolationPoints, do return function (x, overrideDomain = false) { - if(overrideDomain) { - if(isNaN(x)) { + if (overrideDomain) { + if (isNaN(x)) { return NaN; } } else if (!(x >= minx) || !(x <= maxx) || (openMin && x === minx) || (openMax && x === maxx)) { diff --git a/src/Core/utils/math.js b/src/Core/utils/math.js index b883ffb2bf..779fa9cc5c 100644 --- a/src/Core/utils/math.js +++ b/src/Core/utils/math.js @@ -2,33 +2,37 @@ import me from 'math-expressions'; export var appliedFunctionSymbolsDefault = [ "abs", "exp", "log", "ln", "log10", "sign", "sqrt", "erf", - "acos", "acosh", "acot", "acoth", "acsc", "acsch", "asec", - "asech", "asin", "asinh", "atan", "atanh", - "cos", "cosh", "cot", "coth", "csc", "csch", "sec", - "sech", "sin", "sinh", "tan", "tanh", - 'arcsin', 'arccos', 'arctan', 'arccsc', 'arcsec', 'arccot', 'cosec', + "cos", "cosh", "acos", "acosh", 'arccos', 'arccosh', + "cot", "coth", "acot", "acoth", 'arccot', 'arccoth', + "csc", "csch", "acsc", "acsch", 'arccsc', 'arccsch', + "sec", "sech", "asec", "asech", 'arcsec', 'arcsech', + "sin", "sinh", "asin", "asinh", 'arcsin', 'arcsinh', + "tan", "tanh", "atan", "atan2", "atanh", 'arctan', 'arctanh', 'arg', 'min', 'max', 'mean', 'median', 'floor', 'ceil', 'round', 'sum', 'prod', 'variance', 'std', 'count', 'mod', 're', 'im', 'det', 'trace', + 'nPr', 'nCr', ]; export var appliedFunctionSymbolsDefaultLatex = [ "abs", "exp", "log", "ln", "log10", "sign", "sqrt", "erf", - "acos", "acosh", "acot", "acoth", "acsc", "acsch", "asec", - "asech", "asin", "asinh", "atan", "atanh", - "cos", "cosh", "cot", "coth", "csc", "csch", "sec", - "sech", "sin", "sinh", "tan", "tanh", - 'arcsin', 'arccos', 'arctan', 'arccsc', 'arcsec', 'arccot', 'cosec', + "cos", "cosh", "acos", "acosh", 'arccos', 'arccosh', + "cot", "coth", "acot", "acoth", 'arccot', 'arccoth', + "csc", "csch", "acsc", "acsch", 'arccsc', 'arccsch', + "sec", "sech", "asec", "asech", 'arcsec', 'arcsech', + "sin", "sinh", "asin", "asinh", 'arcsin', 'arcsinh', + "tan", "tanh", "atan", "atan2", "atanh", 'arctan', 'arctanh', 'arg', 'min', 'max', 'mean', 'median', 'floor', 'ceil', 'round', 'sum', 'prod', 'variance', 'std', 'count', 'mod', 'Re', 'Im', 'det', 'trace', + 'nPr', 'nCr', ]; -let allowedLatexSymbols = ['alpha', 'beta', 'gamma', 'Gamma', 'delta', 'Delta', 'epsilon', 'zeta', 'eta', 'theta', 'Theta', 'iota', 'kappa', 'lambda', 'Lambda', 'mu', 'nu', 'xi', 'Xi', 'pi', 'Pi', 'rho', 'sigma', 'Sigma', 'tau', 'Tau', 'upsilon', 'Upsilon', 'phi', 'Phi', 'chi', 'psi', 'Psi', 'omega', 'Omega', 'partial', 'varnothing', 'emptyset'] +let allowedLatexSymbols = ['alpha', 'beta', 'gamma', 'Gamma', 'delta', 'Delta', 'epsilon', 'zeta', 'eta', 'theta', 'Theta', 'iota', 'kappa', 'lambda', 'Lambda', 'mu', 'nu', 'xi', 'Xi', 'pi', 'Pi', 'rho', 'sigma', 'Sigma', 'tau', 'Tau', 'upsilon', 'Upsilon', 'phi', 'Phi', 'chi', 'psi', 'Psi', 'omega', 'Omega', 'partial', 'varnothing', 'emptyset', 'angle', 'circ'] export var textToAst = new me.converters.textToAstObj({ appliedFunctionSymbols: appliedFunctionSymbolsDefault @@ -220,7 +224,7 @@ export async function preprocessMathInverseDefinition({ desiredValue, stateValues, variableName = "value", arrayKey, workspace }) { - if ((desiredValue.tree[0] !== "tuple" && desiredValue.tree[0] !== "vector") + if ((desiredValue.tree[0] !== "tuple" && desiredValue.tree[0] !== "vector" && desiredValue.tree[0] !== "altvector") || !desiredValue.tree.includes() ) { return { desiredValue }; @@ -248,7 +252,7 @@ export async function preprocessMathInverseDefinition({ desiredValue, currentValue = currentValue[arrayKey] } - if (currentValue && (currentValue.tree[0] === "tuple" || currentValue.tree[0] === "vector")) { + if (currentValue && (currentValue.tree[0] === "tuple" || currentValue.tree[0] === "vector" || currentValue.tree[0] === "altvector")) { // if we have a currentValue that is a vector // we will merge components from desired value into current value @@ -527,7 +531,7 @@ export function mergeListsWithOtherContainers(tree) { let operator = tree[0]; let operands = tree.slice(1); - if (["tuple", "vector", "list", "set"].includes(operator)) { + if (["tuple", "vector", "altvector", "list", "set"].includes(operator)) { operands = operands.reduce((a, c) => Array.isArray(c) && c[0] === "list" ? [...a, ...c.slice(1)] : [...a, c], []) } diff --git a/src/Viewer/renderers/mathInput.jsx b/src/Viewer/renderers/mathInput.jsx index 068ce9b87e..b24b9a1fd8 100644 --- a/src/Viewer/renderers/mathInput.jsx +++ b/src/Viewer/renderers/mathInput.jsx @@ -23,7 +23,7 @@ import { rendererState } from './useDoenetRenderer'; import './mathInput.css'; // Moved most of checkWorkStyle styling into Button -const Button = styled.button ` +const Button = styled.button` position: relative; width: 24px; height: 24px; @@ -219,7 +219,7 @@ export default function MathInput(props) { mathInputWrapperCursor = 'not-allowed'; } - if(textareaRef.current && textareaRef.current.disabled !== SVs.disabled) { // Update the mathInput ref's disabled state + if (textareaRef.current && textareaRef.current.disabled !== SVs.disabled) { // Update the mathInput ref's disabled state textareaRef.current.disabled = SVs.disabled; } @@ -321,7 +321,7 @@ export default function MathInput(props) { -
+
Date: Thu, 23 Feb 2023 20:35:17 +0000 Subject: [PATCH 2/4] basic support for units, integrals --- .../DoenetML/equality/mathexpressions.cy.js | 160 ++++++++++++++- cypress/e2e/DoenetML/tagSpecific/math.cy.js | 191 ++++++++++++++++-- .../DoenetML/tagSpecific/mathoperators.cy.js | 107 +++++++++- package-lock.json | 14 +- package.json | 2 +- src/Core/components/Math.js | 6 +- src/Core/utils/booleanLogic.js | 21 ++ src/Core/utils/math.js | 14 +- 8 files changed, 480 insertions(+), 35 deletions(-) diff --git a/cypress/e2e/DoenetML/equality/mathexpressions.cy.js b/cypress/e2e/DoenetML/equality/mathexpressions.cy.js index 4eb867ac57..3aa1636b53 100644 --- a/cypress/e2e/DoenetML/equality/mathexpressions.cy.js +++ b/cypress/e2e/DoenetML/equality/mathexpressions.cy.js @@ -178,6 +178,7 @@ describe('Math expressions equality tests', function () { nCr(5,3) = 10 nPr(5,3) = 60 binom(5,3) = 10 + binom(m,n) = nCr(m,n)

`}, "*"); @@ -186,7 +187,7 @@ describe('Math expressions equality tests', function () { cy.get('#\\/_text1').should('contain.text', 'a') - let nTrues = 3, nFalses = 0; + let nTrues = 4, nFalses = 0; for (let i = 1; i <= nTrues; i++) { cy.get(`#\\/t${i}`).should('have.text', "true") } @@ -213,7 +214,6 @@ describe('Math expressions equality tests', function () { doenetML: ` a - ⟨a,b⟩

⟨a,b⟩ = (a,b) ⟨a,b⟩ = (a,b) @@ -252,5 +252,161 @@ describe('Math expressions equality tests', function () { }) + it('angles', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ angle ABC = angle CBA + angle(A,B,C) = angle(C,B,A) + angle A'B'C' = angle C'B'A' + angle ABC = angle(A,B,C) + angle ABC = angle(A,B,C) + angle A'B'C' = angle(A',B',C') + angle A B C = angle(A,B,C) +

+ +

+ angle ABC = angle ACB> + angle ABC = angle A'B'C' + angle(A,B,C) = angle (A,C,B) + angle(A,B,C) = angle (A',B',C') +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + + let nTrues = 7, nFalses = 2; + + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + + it('units', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ 90 deg = pi/2 + 50% = 0.5 + $5 = $3+$2 + 90 deg = 360 deg - 270 deg + 250% = 50% * 5 + $3 = $12 / 4 + sin(45 deg) = 1/sqrt(2) + x% = x/100 + x deg = pi x/180 + (3x)% = x% 3 +

+ +

+ 90 deg = 90 + 50% = 50 + 360 deg = 0 deg + $5 = 5 +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + + let nTrues = 10, nFalses = 4; + + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + + it('some support for interal', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ int f(x) dx = int dx f(x) + int (x*x + x + x - x^2/3) dx = int (2x^2/3 + 2x) dx + int_a^b f(x) dx = int_a^b dx f(x) + int_(a+a)^(b*b) x*x*x dx = int_(2a)^(b^2) x^3dx +

+ +

+ int f(x) dx = int_a^b f(x) dx + int x^2 dx = int x^3 dx + int_a^b f(x) dx = int_c^d f(x) dx + int_a^b x^2 dx = int_a^b x^3 dx +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + + let nTrues = 4, nFalses = 4; + + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + }) \ No newline at end of file diff --git a/cypress/e2e/DoenetML/tagSpecific/math.cy.js b/cypress/e2e/DoenetML/tagSpecific/math.cy.js index 535c283cc4..07e0f0a179 100644 --- a/cypress/e2e/DoenetML/tagSpecific/math.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/math.cy.js @@ -1917,32 +1917,32 @@ describe('Math Tag Tests', function () {

a

xyz

xyz

-

\\var{xyz}

-

\\var{xyz}

+

\\operatorname{xyz}

+

\\operatorname{xyz}

xyz

xyx

xyx

-

\\var{xyx}

-

\\var{xyx}

+

\\operatorname{xyx}

+

\\operatorname{xyx}

xyx

xy_uv

x2_2x

-

\\var{x2}_2x

+

\\operatorname{x2}_2x

2x_x2

-

2x_\\var{x2}

+

2x_\\operatorname{x2}

2x_{x2}

xy uv x2y 2x x2

-

xy uv \\var{x2y} 2x \\var{x2}

+

xy uv \\operatorname{x2y} 2x \\operatorname{x2}

xy_uv

-

\\var{xy}_\\var{uv}

-

\\var{xy}_\\var{uv}

+

\\operatorname{xy}_\\operatorname{uv}

+

\\operatorname{xy}_\\operatorname{uv}

x2_2x

-

\\var{x2}_2x

+

\\operatorname{x2}_2x

2x_x2

-

2x_\\var{x2}

+

2x_\\operatorname{x2}

xy uv x2y 2x x2

-

\\var{xy} \\var{uv} x2y 2x x2

-

\\var{xy} \\var{uv} x2y 2x x2

+

\\operatorname{xy} \\operatorname{uv} x2y 2x x2

+

\\operatorname{xy} \\operatorname{uv} x2y 2x x2

3^x2

3^x2

`}, "*"); @@ -5693,5 +5693,170 @@ describe('Math Tag Tests', function () { }) + it('vec', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + \\vec{a} + vec a + ` }, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get("#\\/_math1 .mjx-mrow").eq(0).should('have.text', '→a') + cy.get("#\\/_math2 .mjx-mrow").eq(0).should('have.text', '→a') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables['/_math1'].stateValues.value).eqls(["vec", "a"]); + expect(stateVariables['/_math2'].stateValues.value).eqls(["vec", "a"]); + }); + + }) + + it('perp', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + v \\perp u + v perp u + v^\\perp + v^perp + ` }, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get("#\\/_math1 .mjx-mrow").eq(0).should('have.text', 'v⊥u') + cy.get("#\\/_math2 .mjx-mrow").eq(0).should('have.text', 'v⊥u') + cy.get("#\\/_math3 .mjx-mrow").eq(0).should('have.text', 'v⊥') + cy.get("#\\/_math4 .mjx-mrow").eq(0).should('have.text', 'v⊥') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables['/_math1'].stateValues.value).eqls(["perp", "v", "u"]); + expect(stateVariables['/_math2'].stateValues.value).eqls(["perp", "v", "u"]); + expect(stateVariables['/_math3'].stateValues.value).eqls(["^", "v", "perp"]); + expect(stateVariables['/_math4'].stateValues.value).eqls(["^", "v", "perp"]); + }); + + + }) + + it('parallel', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + v \\parallel u + v parallel u + ` }, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get("#\\/_math1 .mjx-mrow").eq(0).should('have.text', 'v∥u') + cy.get("#\\/_math2 .mjx-mrow").eq(0).should('have.text', 'v∥u') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables['/_math1'].stateValues.value).eqls(["parallel", "v", "u"]); + expect(stateVariables['/_math2'].stateValues.value).eqls(["parallel", "v", "u"]); + }); + + + }) + + it('basic units', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

+ $5 + 25% + 60 deg + \\$5 + 25\\% + 60^{\\circ} + $5 + 25% + sin(90 deg) +

+

+ $5 + 25% + 60 deg + sin(90 deg) +

+ ` }, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get("#\\/dol5 .mjx-mrow").eq(0).should('have.text', '$5') + cy.get("#\\/perc25 .mjx-mrow").eq(0).should('have.text', '25%') + cy.get("#\\/deg60 .mjx-mrow").eq(0).should('have.text', '60∘') + cy.get("#\\/dol5b .mjx-mrow").eq(0).should('have.text', '$5') + cy.get("#\\/perc25b .mjx-mrow").eq(0).should('have.text', '25%') + cy.get("#\\/deg60b .mjx-mrow").eq(0).should('have.text', '60∘') + cy.get("#\\/dol5c .mjx-mrow").eq(0).should('have.text', '$5') + cy.get("#\\/perc25c .mjx-mrow").eq(0).should('have.text', '25%') + cy.get("#\\/sin90deg .mjx-mrow").eq(0).should('have.text', 'sin(90∘)') + + cy.get("#\\/ndol5").should('have.text', '5') + cy.get("#\\/nperc25").should('have.text', '0.25') + cy.get("#\\/ndeg60").invoke('text').then(text => { + expect(parseFloat(text)).closeTo(Math.PI / 3, 1E-6) + }); + cy.get("#\\/nsin90deg").should('have.text', '1') + + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables['/dol5'].stateValues.value).eqls(["unit", "$", 5]); + expect(stateVariables['/perc25'].stateValues.value).eqls(["unit", 25, "%"]); + expect(stateVariables['/deg60'].stateValues.value).eqls(["unit", 60, "deg"]); + expect(stateVariables['/dol5b'].stateValues.value).eqls(["unit", "$", 5]); + expect(stateVariables['/perc25b'].stateValues.value).eqls(["unit", 25, "%"]); + expect(stateVariables['/deg60b'].stateValues.value).eqls(["unit", 60, "deg"]); + expect(stateVariables['/dol5c'].stateValues.value).eqls(["unit", "$", 5]); + expect(stateVariables['/perc25c'].stateValues.value).eqls(["unit", 25, "%"]); + expect(stateVariables['/ndol5'].stateValues.value).eq(5); + expect(stateVariables['/nperc25'].stateValues.value).eq(.25); + expect(stateVariables['/ndeg60'].stateValues.value).closeTo(Math.PI / 3, 1E-14); + expect(stateVariables['/nsin90deg'].stateValues.value).eq(1); + }); + + + }) + + it('some support for integral', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a +

+ int f(x) dx + int_a^b f(x) dx + \\int f(x) dx + \\int_a^b f(x) dx +

+ ` }, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get("#\\/indefint .mjx-mrow").eq(0).should('have.text', '∫f(x)dx') + cy.get("#\\/defint .mjx-mrow").eq(0).should('have.text', '∫baf(x)dx') + cy.get("#\\/indefintb .mjx-mrow").eq(0).should('have.text', '∫f(x)dx') + cy.get("#\\/defintb .mjx-mrow").eq(0).should('have.text', '∫baf(x)dx') + + + }) + }) diff --git a/cypress/e2e/DoenetML/tagSpecific/mathoperators.cy.js b/cypress/e2e/DoenetML/tagSpecific/mathoperators.cy.js index 8d99f7b2e3..bb9f85a92e 100644 --- a/cypress/e2e/DoenetML/tagSpecific/mathoperators.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/mathoperators.cy.js @@ -2092,6 +2092,109 @@ describe('Math Operator Tag Tests', function () { }) }) + it('floor and ceil as math expression', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + \\lfloor 55.3252326 \\rfloor + floor(55.3252326) + + + \\lceil \\log(31.1) \\rceil + ceil(log(31.1)) + + + + \\lfloor $floor1/$ceil1 \\rfloor + floor($floor1/$ceil1) + \\lceil $ceil1/$floor1 \\rceil + ceil($ceil1/$floor1) + +

Allow for slight roundoff error: + \\lfloor 3.999999999999999 \\rfloor + floor 3.999999999999999 + \\lceil -6999.999999999999 \\rceil + ceil -6999.999999999999 +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait for page to load + + cy.get('#\\/floor1').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('⌊55.3252326⌋') + }); + cy.get('#\\/floor2').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('⌊55.3252326⌋') + }); + cy.get('#\\/floor1simp').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('55') + }); + cy.get('#\\/floor2simp').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('55') + }); + cy.get('#\\/ceil1').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('⌈log(31.1)⌉') + }); + cy.get('#\\/ceil2').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('⌈log(31.1)⌉') + }); + cy.get('#\\/ceil1simp').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('4') + }); + cy.get('#\\/ceil2simp').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('4') + }); + cy.get('#\\/floor3').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('13') + }); + cy.get('#\\/floor4').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('13') + }); + cy.get('#\\/ceil3').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('1') + }); + cy.get('#\\/ceil4').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('1') + }); + cy.get('#\\/floor5').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('4') + }); + cy.get('#\\/floor6').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('4') + }); + cy.get('#\\/ceil5').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('−7000') + }); + cy.get('#\\/ceil6').find('.mjx-mrow').eq(0).invoke('text').then((text) => { + expect(text.trim()).equal('−7000') + }); + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables['/floor1'].stateValues.value).eqls(["apply", "floor", 55.3252326]); + expect(stateVariables['/floor2'].stateValues.value).eqls(["apply", "floor", 55.3252326]); + expect(stateVariables['/floor1simp'].stateValues.value).eq(55); + expect(stateVariables['/floor2simp'].stateValues.value).eq(55); + expect(stateVariables['/ceil1'].stateValues.value).eqls(["apply", "ceil", ["apply", "log", 31.1]]); + expect(stateVariables['/ceil2'].stateValues.value).eqls(["apply", "ceil", ["apply", "log", 31.1]]); + expect(stateVariables['/ceil1simp'].stateValues.value).eq(4); + expect(stateVariables['/ceil2simp'].stateValues.value).eq(4); + expect(stateVariables['/floor3'].stateValues.value).eq(13); + expect(stateVariables['/floor4'].stateValues.value).eq(13); + expect(stateVariables['/ceil3'].stateValues.value).eq(1); + expect(stateVariables['/ceil4'].stateValues.value).eq(1); + expect(stateVariables['/floor5'].stateValues.value).eq(4); + expect(stateVariables['/floor6'].stateValues.value).eq(4); + expect(stateVariables['/ceil5'].stateValues.value).eq(-7000); + expect(stateVariables['/ceil6'].stateValues.value).eq(-7000); + + }) + + }) + it('abs', () => { cy.window().then(async (win) => { win.postMessage({ @@ -5373,7 +5476,7 @@ describe('Math Operator Tag Tests', function () { cy.get('#\\/mimaths01 textarea').type("{end}{backspace}8{enter}", { force: true }); cy.get('#\\/maths01 .mjx-mrow').should('contain.text', '6') - + cy.get('#\\/numbers00 .mjx-mrow').eq(0).should('have.text', '3') cy.get('#\\/numbers01 .mjx-mrow').eq(0).should('have.text', '6') cy.get('#\\/numbers10 .mjx-mrow').eq(0).should('have.text', '3') @@ -6028,7 +6131,7 @@ describe('Math Operator Tag Tests', function () { cy.get('#\\/mimaths10 textarea').type("{end}{backspace}2{enter}", { force: true }); cy.get('#\\/maths10 .mjx-mrow').should('contain.text', '3') - + cy.get('#\\/numbers00 .mjx-mrow').eq(0).should('have.text', '6') cy.get('#\\/numbers01 .mjx-mrow').eq(0).should('have.text', '6') cy.get('#\\/numbers10 .mjx-mrow').eq(0).should('have.text', '3') diff --git a/package-lock.json b/package-lock.json index 3799be65a4..9b8fdc03f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "json-stringify-deterministic": "^1.0.1", "lodash.debounce": "^4.0.8", "lorem-ipsum": "^2.0.4", - "math-expressions": "^2.0.0-alpha54", + "math-expressions": "^2.0.0-alpha56", "nanoid": "^3.1.31", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.3", @@ -8314,9 +8314,9 @@ "license": "Apache-2.0" }, "node_modules/math-expressions": { - "version": "2.0.0-alpha54", - "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha54.tgz", - "integrity": "sha512-Q7Z4sO8vFzd9b9cd/yc6jO3zUN0PWn5pAixpM7Ukqow75XN1VjrWP1E8LTMgjtUGc7nwdwqNDOqX4/QpkD+PGA==", + "version": "2.0.0-alpha56", + "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha56.tgz", + "integrity": "sha512-KjsAwpHs2ZWd/9ika1HfBw/mAwXR5UUVW9SlOy8kvK2DVX292+WEdTfDiozEFi7eROHT1REL/gig2zK4IOWtxw==", "dependencies": { "@babel/cli": "^7.0.0", "babel-upgrade": "^1.0.1", @@ -17960,9 +17960,9 @@ "dev": true }, "math-expressions": { - "version": "2.0.0-alpha54", - "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha54.tgz", - "integrity": "sha512-Q7Z4sO8vFzd9b9cd/yc6jO3zUN0PWn5pAixpM7Ukqow75XN1VjrWP1E8LTMgjtUGc7nwdwqNDOqX4/QpkD+PGA==", + "version": "2.0.0-alpha56", + "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha56.tgz", + "integrity": "sha512-KjsAwpHs2ZWd/9ika1HfBw/mAwXR5UUVW9SlOy8kvK2DVX292+WEdTfDiozEFi7eROHT1REL/gig2zK4IOWtxw==", "requires": { "@babel/cli": "^7.0.0", "babel-upgrade": "^1.0.1", diff --git a/package.json b/package.json index 2d8f7f00bd..58a8d7f05d 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "json-stringify-deterministic": "^1.0.1", "lodash.debounce": "^4.0.8", "lorem-ipsum": "^2.0.4", - "math-expressions": "^2.0.0-alpha54", + "math-expressions": "^2.0.0-alpha56", "nanoid": "^3.1.31", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.3", diff --git a/src/Core/components/Math.js b/src/Core/components/Math.js index 0c6390fcfb..bc8f4b5b75 100644 --- a/src/Core/components/Math.js +++ b/src/Core/components/Math.js @@ -2200,7 +2200,7 @@ function calculateExpressionWithCodes({ dependencyValues, changes }) { if (dependencyValues.format === 'latex') { // for latex, must explicitly denote that code // is a multicharacter variable - nextString = '\\var{' + code + '}'; + nextString = '\\operatorname{' + code + '}'; } else { // for text, just make sure code is surrounded by spaces @@ -2369,7 +2369,7 @@ function calculateCodesAdjacentToStrings({ dependencyValues }) { let subCodes = {}; if (mathInd !== undefined) { if (dependencyValues.format === "latex") { - subCodes.prevCode = '\\var{' + dependencyValues.codePre + mathInd + '}'; + subCodes.prevCode = '\\operatorname{' + dependencyValues.codePre + mathInd + '}'; } else { subCodes.prevCode = dependencyValues.codePre + mathInd; } @@ -2383,7 +2383,7 @@ function calculateCodesAdjacentToStrings({ dependencyValues }) { } if (dependencyValues.format === "latex") { - subCodes.nextCode = '\\var{' + dependencyValues.codePre + nextInd + '}'; + subCodes.nextCode = '\\operatorname{' + dependencyValues.codePre + nextInd + '}'; } else { subCodes.nextCode = dependencyValues.codePre + nextInd; } diff --git a/src/Core/utils/booleanLogic.js b/src/Core/utils/booleanLogic.js index 9170662cd3..c1cd72f81e 100644 --- a/src/Core/utils/booleanLogic.js +++ b/src/Core/utils/booleanLogic.js @@ -841,6 +841,27 @@ export function splitSymbolsIfMath({ logicTree, nonMathCodes, foundNonMath = fal nonMathCodes, foundNonMath, init: false }))] + } else if (operator === "angle") { + let newOperands = []; + for (let op of operands) { + if (typeof op === "string" && !foundNonMath) { + let splitResult = fromTextSplit(op).tree; + if (splitResult[0] === "*") { + newOperands.push(...splitResult.slice(1)) + } else { + newOperands.push(splitResult) + } + } else { + newOperands.push( + splitSymbolsIfMath({ + logicTree: op, + nonMathCodes, foundNonMath, + init: false + }) + ) + } + } + return [operator, ...newOperands]; } else { return [operator, ...operands.map(x => splitSymbolsIfMath({ logicTree: x, diff --git a/src/Core/utils/math.js b/src/Core/utils/math.js index 779fa9cc5c..15c4378972 100644 --- a/src/Core/utils/math.js +++ b/src/Core/utils/math.js @@ -32,7 +32,7 @@ export var appliedFunctionSymbolsDefaultLatex = [ 'nPr', 'nCr', ]; -let allowedLatexSymbols = ['alpha', 'beta', 'gamma', 'Gamma', 'delta', 'Delta', 'epsilon', 'zeta', 'eta', 'theta', 'Theta', 'iota', 'kappa', 'lambda', 'Lambda', 'mu', 'nu', 'xi', 'Xi', 'pi', 'Pi', 'rho', 'sigma', 'Sigma', 'tau', 'Tau', 'upsilon', 'Upsilon', 'phi', 'Phi', 'chi', 'psi', 'Psi', 'omega', 'Omega', 'partial', 'varnothing', 'emptyset', 'angle', 'circ'] +let allowedLatexSymbols = ['alpha', 'beta', 'gamma', 'Gamma', 'delta', 'Delta', 'epsilon', 'zeta', 'eta', 'theta', 'Theta', 'iota', 'kappa', 'lambda', 'Lambda', 'mu', 'nu', 'xi', 'Xi', 'pi', 'Pi', 'rho', 'sigma', 'Sigma', 'tau', 'Tau', 'upsilon', 'Upsilon', 'phi', 'Phi', 'chi', 'psi', 'Psi', 'omega', 'Omega', 'partial', 'varnothing', 'emptyset', 'angle', 'circ', '$', '%'] export var textToAst = new me.converters.textToAstObj({ appliedFunctionSymbols: appliedFunctionSymbolsDefault @@ -543,11 +543,11 @@ export function mergeListsWithOtherContainers(tree) { export function wrapWordWithVar(string, parseScientificNotation) { - // wrap words that aren't already in a \var with a \var + // wrap words that aren't already in a \operatorname with a \operatorname let newString = ""; - let regex = /\\var\s*{[^{}]*}/ + let regex = /\\operatorname\s*{[^{}]*}/ let match = string.match(regex); while (match) { let beginMatch = match.index; @@ -597,7 +597,7 @@ function wrapWordWithVarSub(string, parseScientificNotation) { } else { let beginWord = beginMatch + match[1].length; newString += string.substring(0, beginWord); - newString += `\\var{${match[2]}}`; + newString += `\\operatorname{${match[2]}}`; string = string.substring(endMatch); } @@ -614,7 +614,7 @@ export function wrapWordIncludingNumberWithVar(string, parseScientificNotation) let newString = ""; - let regex = /\\var\s*{[^{}]*}/ + let regex = /\\operatorname\s*{[^{}]*}/ let match = string.match(regex); while (match) { let beginMatch = match.index; @@ -665,7 +665,7 @@ function wrapWordIncludingNumberWithVarSub(string, parseScientificNotation) { } else { let beginWord = beginMatch + match[1].length; newString += string.substring(0, beginWord); - newString += `\\var{${match[2]}}`; + newString += `\\operatorname{${match[2]}}`; string = string.substring(endMatch); } @@ -679,7 +679,7 @@ function wrapWordIncludingNumberWithVarSub(string, parseScientificNotation) { } export function stripLatex(latex) { - return latex.replaceAll(`\\,`, '').replaceAll(/\\var{([^{}]*)}/g, '$1'); + return latex.replaceAll(`\\,`, '').replaceAll(/\\operatorname{([^{}]*)}/g, '$1'); } export function superSubscriptsToUnicode(text) { From d0273f6ee7d5f090d68b09ce622a96c4326cfe29 Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Tue, 28 Feb 2023 16:21:08 +0000 Subject: [PATCH 3/4] linesegment math operator --- .../DoenetML/equality/mathexpressions.cy.js | 105 +++++++++++++++++- cypress/e2e/DoenetML/tagSpecific/math.cy.js | 23 ++++ package-lock.json | 14 +-- package.json | 2 +- 4 files changed, 132 insertions(+), 12 deletions(-) diff --git a/cypress/e2e/DoenetML/equality/mathexpressions.cy.js b/cypress/e2e/DoenetML/equality/mathexpressions.cy.js index 3aa1636b53..b38b1cca2f 100644 --- a/cypress/e2e/DoenetML/equality/mathexpressions.cy.js +++ b/cypress/e2e/DoenetML/equality/mathexpressions.cy.js @@ -45,7 +45,7 @@ describe('Math expressions equality tests', function () { cy.get('#\\/_text1').should('contain.text', 'a') - let nTrues = 6, nFalses = 2; + let nTrues = 9, nFalses = 3; for (let i = 1; i <= nTrues; i++) { cy.get(`#\\/t${i}`).should('have.text', "true") } @@ -266,10 +266,12 @@ describe('Math expressions equality tests', function () { angle ABC = angle(A,B,C) angle A'B'C' = angle(A',B',C') angle A B C = angle(A,B,C) + angle ABC = angle CBA + angle(A,B,C) = angle(C,B,A)

- angle ABC = angle ACB> + angle ABC = angle ACB angle ABC = angle A'B'C' angle(A,B,C) = angle (A,C,B) angle(A,B,C) = angle (A',B',C') @@ -282,7 +284,7 @@ describe('Math expressions equality tests', function () { - let nTrues = 7, nFalses = 2; + let nTrues = 9, nFalses = 4; for (let i = 1; i <= nTrues; i++) { cy.get(`#\\/t${i}`).should('have.text', "true") @@ -359,7 +361,7 @@ describe('Math expressions equality tests', function () { }) - it('some support for interal', () => { + it('some support for integral', () => { cy.window().then(async (win) => { win.postMessage({ doenetML: ` @@ -408,5 +410,100 @@ describe('Math expressions equality tests', function () { }) + it('vecs', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ vec(x) = vec x + vec(x) + vec(x) = 2vec(x) + vec(x)*vec(x)vec(y)/(vec(x)*vec(x)) = vec(y) +

+ +

+ vec(x) = x + vec(xy) = vec(x)vec(y) + vec(2x) = 2vec(x) +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + + let nTrues = 3, nFalses = 3; + + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + + it('linesegments', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + +

+ linesegment(A,B) = linesegment(B,A) + vec(x) + vec(x) = 2vec(x) + vec(x)*vec(x)vec(y)/(vec(x)*vec(x)) = vec(y) + linesegment(A,B) = linesegment(B,A) +

+ +

+ vec(x) = x + vec(xy) = vec(x)vec(y) + vec(2x) = 2vec(x) +

+ + `}, "*"); + }); + + cy.get('#\\/_text1').should('contain.text', 'a') + + + + let nTrues = 4, nFalses = 3; + + for (let i = 1; i <= nTrues; i++) { + cy.get(`#\\/t${i}`).should('have.text', "true") + } + + for (let i = 1; i <= nFalses; i++) { + cy.get(`#\\/f${i}`).should('have.text', "false") + } + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + for (let i = 1; i <= nTrues; i++) { + expect(stateVariables[`/t${i}`].stateValues.value).to.be.true + } + for (let i = 1; i <= nFalses; i++) { + expect(stateVariables[`/f${i}`].stateValues.value).to.be.false + } + }) + + }) + }) \ No newline at end of file diff --git a/cypress/e2e/DoenetML/tagSpecific/math.cy.js b/cypress/e2e/DoenetML/tagSpecific/math.cy.js index 07e0f0a179..569d607a2d 100644 --- a/cypress/e2e/DoenetML/tagSpecific/math.cy.js +++ b/cypress/e2e/DoenetML/tagSpecific/math.cy.js @@ -5716,6 +5716,29 @@ describe('Math Tag Tests', function () { }) + it('line segment', () => { + cy.window().then(async (win) => { + win.postMessage({ + doenetML: ` + a + \\overline{AB} + linesegment(A,B) + ` }, "*"); + }); + + cy.get('#\\/_text1').should('have.text', 'a'); // to wait until loaded + + cy.get("#\\/_math1 .mjx-mrow").eq(0).should('have.text', '¯¯¯¯¯¯¯¯AB') + cy.get("#\\/_math2 .mjx-mrow").eq(0).should('have.text', '¯¯¯¯¯¯¯¯AB') + + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables['/_math1'].stateValues.value).eqls(["linesegment", "A", "B"]); + expect(stateVariables['/_math2'].stateValues.value).eqls(["linesegment", "A", "B"]); + }); + + }) + it('perp', () => { cy.window().then(async (win) => { win.postMessage({ diff --git a/package-lock.json b/package-lock.json index 9b8fdc03f8..d105a1a92d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "json-stringify-deterministic": "^1.0.1", "lodash.debounce": "^4.0.8", "lorem-ipsum": "^2.0.4", - "math-expressions": "^2.0.0-alpha56", + "math-expressions": "^2.0.0-alpha58", "nanoid": "^3.1.31", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.3", @@ -8314,9 +8314,9 @@ "license": "Apache-2.0" }, "node_modules/math-expressions": { - "version": "2.0.0-alpha56", - "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha56.tgz", - "integrity": "sha512-KjsAwpHs2ZWd/9ika1HfBw/mAwXR5UUVW9SlOy8kvK2DVX292+WEdTfDiozEFi7eROHT1REL/gig2zK4IOWtxw==", + "version": "2.0.0-alpha58", + "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha58.tgz", + "integrity": "sha512-7kWVsdbw7To6wJtrCjF0eBdMP/9jLWpdDdEAj6AzrDQLBAlsb1KLsSsBIPERj/2OON5VRAh5X6ivngL6nUmUKQ==", "dependencies": { "@babel/cli": "^7.0.0", "babel-upgrade": "^1.0.1", @@ -17960,9 +17960,9 @@ "dev": true }, "math-expressions": { - "version": "2.0.0-alpha56", - "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha56.tgz", - "integrity": "sha512-KjsAwpHs2ZWd/9ika1HfBw/mAwXR5UUVW9SlOy8kvK2DVX292+WEdTfDiozEFi7eROHT1REL/gig2zK4IOWtxw==", + "version": "2.0.0-alpha58", + "resolved": "https://registry.npmjs.org/math-expressions/-/math-expressions-2.0.0-alpha58.tgz", + "integrity": "sha512-7kWVsdbw7To6wJtrCjF0eBdMP/9jLWpdDdEAj6AzrDQLBAlsb1KLsSsBIPERj/2OON5VRAh5X6ivngL6nUmUKQ==", "requires": { "@babel/cli": "^7.0.0", "babel-upgrade": "^1.0.1", diff --git a/package.json b/package.json index 58a8d7f05d..aece98a711 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "json-stringify-deterministic": "^1.0.1", "lodash.debounce": "^4.0.8", "lorem-ipsum": "^2.0.4", - "math-expressions": "^2.0.0-alpha56", + "math-expressions": "^2.0.0-alpha58", "nanoid": "^3.1.31", "react": "^17.0.2", "react-copy-to-clipboard": "^5.0.3", From ce91c40b7481d8678e3e7ee0a156309d144fe342 Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Tue, 28 Feb 2023 22:10:48 +0000 Subject: [PATCH 4/4] refactor to use a vectorOperators array --- .../DiscreteSimulationResultList.js | 4 +- .../DiscreteSimulationResultPolyline.js | 3 +- src/Core/components/Evaluate.js | 3 +- src/Core/components/Function.js | 4 +- src/Core/components/FunctionIterates.js | 3 +- src/Core/components/Math.js | 33 ++++++++-------- src/Core/components/MatrixInput.js | 38 +++++++++---------- src/Core/components/Point.js | 8 ++-- src/Core/components/Ray.js | 8 ++-- src/Core/components/Spreadsheet.js | 6 +-- src/Core/components/Vector.js | 12 +++--- src/Core/utils/checkEquality.js | 10 +++-- src/Core/utils/function.js | 6 +-- src/Core/utils/math.js | 10 +++-- 14 files changed, 77 insertions(+), 71 deletions(-) diff --git a/src/Core/components/DiscreteSimulationResultList.js b/src/Core/components/DiscreteSimulationResultList.js index 7f231feecb..4902fc576c 100644 --- a/src/Core/components/DiscreteSimulationResultList.js +++ b/src/Core/components/DiscreteSimulationResultList.js @@ -1,4 +1,4 @@ -import { roundForDisplay } from '../utils/math'; +import { roundForDisplay, vectorOperators } from '../utils/math'; import BlockComponent from './abstract/BlockComponent'; @@ -210,7 +210,7 @@ export default class DiscreteSimulationResultList extends BlockComponent { if (dependencyValues.allIterates.length > 0 && Array.isArray(dependencyValues.allIterates[0].tree) && - ["vector", "altvector", "tuple"].includes(dependencyValues.allIterates[0].tree[0]) + vectorOperators.includes(dependencyValues.allIterates[0].tree[0]) ) { nComponents = dependencyValues.allIterates[0].tree.length - 1; haveVector = true; diff --git a/src/Core/components/DiscreteSimulationResultPolyline.js b/src/Core/components/DiscreteSimulationResultPolyline.js index 9e02f68cce..3b3d24466c 100644 --- a/src/Core/components/DiscreteSimulationResultPolyline.js +++ b/src/Core/components/DiscreteSimulationResultPolyline.js @@ -1,5 +1,6 @@ import GraphicalComponent from './abstract/GraphicalComponent'; import me from 'math-expressions'; +import { vectorOperators } from '../utils/math'; export default class DiscreteSimulationResultPolyline extends GraphicalComponent { constructor(args) { @@ -107,7 +108,7 @@ export default class DiscreteSimulationResultPolyline extends GraphicalComponent setValue: { allIterates: dependencyValues.allIteratesSub.filter(x => Number.isFinite(x.tree) || - (Array.isArray(x.tree) && ["tuple", "vector", "altvector"].includes(x.tree[0]) && x.tree.slice(1).every(Number.isFinite)) + (Array.isArray(x.tree) && vectorOperators.includes(x.tree[0]) && x.tree.slice(1).every(Number.isFinite)) ) } } diff --git a/src/Core/components/Evaluate.js b/src/Core/components/Evaluate.js index 3d89aec4fd..6409f84017 100644 --- a/src/Core/components/Evaluate.js +++ b/src/Core/components/Evaluate.js @@ -1,5 +1,6 @@ import MathComponent from './Math'; import me from 'math-expressions'; +import { vectorOperators } from '../utils/math'; export default class Evaluate extends MathComponent { static componentType = "evaluate"; @@ -351,7 +352,7 @@ export default class Evaluate extends MathComponent { // if have a single input, check if it is a vector if (input.length === 1) { let inputTree = input[0].tree; - if (Array.isArray(inputTree) && ["vector", "altvector", "tuple"].includes(inputTree[0])) { + if (Array.isArray(inputTree) && vectorOperators.includes(inputTree[0])) { input = inputTree.slice(1).map(x => me.fromAst(x)); } } diff --git a/src/Core/components/Function.js b/src/Core/components/Function.js index ce9c7b4278..7f131c3ce7 100644 --- a/src/Core/components/Function.js +++ b/src/Core/components/Function.js @@ -1,7 +1,7 @@ import InlineComponent from './abstract/InlineComponent'; import GraphicalComponent from './abstract/GraphicalComponent'; import me from 'math-expressions'; -import { normalizeMathExpression, returnNVariables, roundForDisplay } from '../utils/math'; +import { normalizeMathExpression, returnNVariables, roundForDisplay, vectorOperators } from '../utils/math'; import { returnInterpolatedFunction, returnNumericalFunctionFromFormula, returnReturnDerivativesOfInterpolatedFunction, returnSymbolicFunctionFromFormula } from '../utils/function'; export default class Function extends InlineComponent { @@ -605,7 +605,7 @@ export default class Function extends InlineComponent { } else if (dependencyValues.mathChild.length > 0) { let formula = dependencyValues.mathChild[0].stateValues.value; let formulaIsVectorValued = Array.isArray(formula.tree) && - ["tuple", "vector", "altvector"].includes(formula.tree[0]); + vectorOperators.includes(formula.tree[0]); let nOutputs = 1; if (formulaIsVectorValued) { diff --git a/src/Core/components/FunctionIterates.js b/src/Core/components/FunctionIterates.js index a0fe3538dc..709ac4225e 100644 --- a/src/Core/components/FunctionIterates.js +++ b/src/Core/components/FunctionIterates.js @@ -1,5 +1,6 @@ import InlineComponent from './abstract/InlineComponent'; import me from 'math-expressions'; +import { vectorOperators } from '../utils/math'; export default class FunctionIterates extends InlineComponent { static componentType = "functionIterates"; @@ -117,7 +118,7 @@ export default class FunctionIterates extends InlineComponent { !functionComp || dependencyValues.nDimensions === 0 || !(dependencyValues.nDimensions === 1 || Array.isArray(initialValue.tree) - && ["vector", "altvector", "tuple"].includes(initialValue.tree[0]) + && vectorOperators.includes(initialValue.tree[0]) && initialValue.tree.length === dependencyValues.nDimensions + 1 ) ) { diff --git a/src/Core/components/Math.js b/src/Core/components/Math.js index bc8f4b5b75..b7b13c6944 100644 --- a/src/Core/components/Math.js +++ b/src/Core/components/Math.js @@ -1,9 +1,10 @@ import InlineComponent from './abstract/InlineComponent'; import me from 'math-expressions'; -import { getFromText, getFromLatex, convertValueToMathExpression, normalizeMathExpression, roundForDisplay, mergeListsWithOtherContainers, preprocessMathInverseDefinition, superSubscriptsToUnicode, unicodeToSuperSubscripts } from '../utils/math'; +import { getFromText, getFromLatex, convertValueToMathExpression, normalizeMathExpression, roundForDisplay, mergeListsWithOtherContainers, preprocessMathInverseDefinition, superSubscriptsToUnicode, unicodeToSuperSubscripts, vectorOperators } from '../utils/math'; import { flattenDeep } from '../utils/array'; import { returnSelectedStyleStateVariableDefinition } from '../utils/style'; +const vectorAndListOperators = ["list", ...vectorOperators]; export default class MathComponent extends InlineComponent { constructor(args) { @@ -1422,7 +1423,7 @@ export default class MathComponent extends InlineComponent { if (nMathChildren === 0 || !Array.isArray(expressionWithCodesTree) || - !["tuple", "vector", "altvector"].includes(expressionWithCodesTree[0]) + !vectorOperators.includes(expressionWithCodesTree[0]) ) { return { setValue: { mathChildrenByVectorComponent: null } }; } @@ -1478,7 +1479,7 @@ export default class MathComponent extends InlineComponent { let tree = dependencyValues.value.tree; if (Array.isArray(tree)) { - if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { + if (vectorAndListOperators.includes(tree[0])) { nDimensions = tree.length - 1; } else if (tree[0] === "matrix") { let size = tree[1].slice(1); @@ -1488,7 +1489,7 @@ export default class MathComponent extends InlineComponent { } else if (size[1] === 1) { nDimensions = size[0]; } - } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") + } else if (vectorOperators.includes(tree[1][0]) && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { nDimensions = tree[1].length - 1; @@ -1544,7 +1545,7 @@ export default class MathComponent extends InlineComponent { let vector = {}; if (Array.isArray(tree)) { - if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { + if (vectorAndListOperators.includes(tree[0])) { for (let ind = 0; ind < arraySize[0]; ind++) { vector[ind] = me.fromAst(tree[ind + 1]); } @@ -1562,7 +1563,7 @@ export default class MathComponent extends InlineComponent { } createdVector = true; } - } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") + } else if (vectorOperators.includes(tree[1][0]) && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { for (let ind = 0; ind < arraySize[0]; ind++) { @@ -1598,7 +1599,7 @@ export default class MathComponent extends InlineComponent { let desiredValue; let tree = globalDependencyValues.value.tree; if (Array.isArray(tree)) { - if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { + if (vectorAndListOperators.includes(tree[0])) { desiredValue = me.fromAst([tree[0], ...workspace.desiredVector.map(x => x.tree)]) } else if (tree[0] === "matrix") { let size = tree[1].slice(1); @@ -1616,7 +1617,7 @@ export default class MathComponent extends InlineComponent { } desiredValue = me.fromAst(["matrix", tree[1], desiredMatrixVals]) } - } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") + } else if (vectorOperators.includes(tree[1][0]) && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { desiredValue = [tree[0], [tree[1][0], ...workspace.desiredVector.map(x => x.tree)]] @@ -1677,11 +1678,11 @@ export default class MathComponent extends InlineComponent { let tree = dependencyValues.value.tree; if (Array.isArray(tree)) { - if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { + if (vectorAndListOperators.includes(tree[0])) { matrixSize = [tree.length - 1, 1]; } else if (tree[0] === "matrix") { matrixSize = tree[1].slice(1); - } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") + } else if (vectorOperators.includes(tree[1][0]) && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { matrixSize = [1, tree[1].length - 1]; @@ -1886,7 +1887,7 @@ export default class MathComponent extends InlineComponent { let matrix = {}; if (Array.isArray(tree)) { - if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { + if (vectorAndListOperators.includes(tree[0])) { for (let ind = 0; ind < arraySize[0]; ind++) { matrix[ind + ",0"] = me.fromAst(tree[ind + 1]); } @@ -1899,7 +1900,7 @@ export default class MathComponent extends InlineComponent { } } createdMatrix = true; - } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") + } else if (vectorOperators.includes(tree[1][0]) && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { for (let ind = 0; ind < arraySize[1]; ind++) { @@ -1937,7 +1938,7 @@ export default class MathComponent extends InlineComponent { let desiredValue; let tree = globalDependencyValues.value.tree; if (Array.isArray(tree)) { - if (["vector", "altvector", "tuple", "list"].includes(tree[0])) { + if (vectorAndListOperators.includes(tree[0])) { desiredValue = [tree[0]] for (let ind = 0; ind < arraySize[0]; ind++) { desiredValue.push(workspace.desiredMatrix[ind + ",0"].tree) @@ -1954,7 +1955,7 @@ export default class MathComponent extends InlineComponent { desiredMatrixVals.push(row); } desiredValue = me.fromAst(["matrix", tree[1], desiredMatrixVals]) - } else if ((tree[1][0] === "vector" || tree[1][0] === "altvector" || tree[1][0] === "tuple") + } else if (vectorOperators.includes(tree[1][0]) && ((tree[0] === "^" && tree[2] === "T") || tree[0] === "prime") ) { @@ -2553,7 +2554,7 @@ function checkForLinearExpression(tree, variables, inverseTree, constants = [], let operands = tree.slice(1); // for container, check if at least one component is a linear expression - if (operator === "tuple" || operator === "vector" || operator === "altvector" || operator === "list") { + if (vectorAndListOperators.includes(operator)) { let result = { mappings: {}, template: [operator] };//, modifiableStrings: {}}; let numLinear = 0; @@ -2809,7 +2810,7 @@ async function invertMath({ desiredStateVariableValues, dependencyValues, } } - if (["vector", "altvector", "tuple", "list"].includes(newExpressionWithCodes.tree[0]) && + if (vectorAndListOperators.includes(newExpressionWithCodes.tree[0]) && !newExpressionWithCodes.tree.slice(1).every(mathComponentContainsCode) ) { diff --git a/src/Core/components/MatrixInput.js b/src/Core/components/MatrixInput.js index 9c93d49bce..afac0ad8ac 100644 --- a/src/Core/components/MatrixInput.js +++ b/src/Core/components/MatrixInput.js @@ -1,7 +1,7 @@ import Input from './abstract/Input'; import me from 'math-expressions'; import { deepClone, deepCompare } from '../utils/deepFunctions'; -import { convertValueToMathExpression, getFromLatex, normalizeLatexString, roundForDisplay, stripLatex } from '../utils/math'; +import { convertValueToMathExpression, getFromLatex, normalizeLatexString, roundForDisplay, stripLatex, vectorOperators } from '../utils/math'; import CompositeComponent from './abstract/CompositeComponent'; import BaseComponent from './abstract/BaseComponent'; @@ -338,7 +338,7 @@ export class MatrixInput extends Input { let operator = originalTree[0]; if (operator === "matrix") { numRows = originalTree[1][1]; - } else if (operator === "vector" || operator === "altvector" || operator == "tuple") { + } else if (vectorOperators.includes(operator)) { numRows = originalTree.length - 1; } @@ -366,7 +366,7 @@ export class MatrixInput extends Input { let originalTree = dependencyValues.valueOriginal.tree; let defaultEntryTree = (await stateValues.defaultEntry).tree; if (await stateValues.numColumns === 1 && Array.isArray(originalTree) - && (originalTree[0] === "vector" || originalTree[0] === "altvector" || originalTree[0] === "tuple") + && vectorOperators.includes(originalTree[0]) ) { // original value was a vector // so we keep it a vector @@ -483,7 +483,7 @@ export class MatrixInput extends Input { if (operator === "matrix") { numColumns = originalTree[1][2]; } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { numColumns = originalTree[1].length - 1; @@ -514,7 +514,7 @@ export class MatrixInput extends Input { let operator = originalTree[0]; if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { @@ -627,7 +627,7 @@ export class MatrixInput extends Input { return { setValue: { accumulatedComponents } } - } else if (operator === "vector" || operator === "altvector" || operator === "tuple") { + } else if (vectorOperators.includes(operator)) { // treat vector/tuple as first column in matrix for (let [rowInd, comp] of originalTree.slice(1).entries()) { @@ -641,7 +641,7 @@ export class MatrixInput extends Input { return { setValue: { accumulatedComponents } } } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { // treat transpose of vector/tuple as first row in matrix @@ -796,7 +796,7 @@ export class MatrixInput extends Input { return { setValue: { componentValues } } - } else if (operator === "vector" || operator === "altvector" || operator === "tuple") { + } else if (vectorOperators.includes(operator)) { // treat vector/tuple as first column in matrix @@ -830,7 +830,7 @@ export class MatrixInput extends Input { return { setValue: { componentValues } } } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { @@ -921,12 +921,12 @@ export class MatrixInput extends Input { if (Array.isArray(originalTree)) { let operator = originalTree[0]; - if (operator === "vector" || operator === "altvector" || operator === "tuple") { + if (vectorOperators.includes(operator)) { originalIsColumnVector = true; } else if (operator === "matrix") { originalIsMatrix = true; } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { originalIsRowVector = true; @@ -1194,7 +1194,7 @@ export class MatrixInput extends Input { return { setValue: { componentImmediateValues } } - } else if (operator === "vector" || operator === "altvector" || operator === "tuple") { + } else if (vectorOperators.includes(operator)) { // treat vector/tuple as first column in matrix @@ -1228,7 +1228,7 @@ export class MatrixInput extends Input { return { setValue: { componentImmediateValues } } } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { @@ -1319,12 +1319,12 @@ export class MatrixInput extends Input { if (Array.isArray(originalTree)) { let operator = originalTree[0]; - if (operator === "vector" || operator === "altvector" || operator === "tuple") { + if (vectorOperators.includes(operator)) { originalIsColumnVector = true; } else if (operator === "matrix") { originalIsMatrix = true; } else if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { originalIsRowVector = true; @@ -1601,7 +1601,7 @@ export class MatrixInput extends Input { if (Array.isArray(originalTree)) { let operator = originalTree[0]; - if (operator === "vector" || operator === "altvector" || operator === "tuple") { + if (vectorOperators.includes(operator)) { // if original value was a vector, then keep it as a vector let desiredValue = me.fromAst([operator, ...desiredTree[2].slice(1).map(x => x[1])]) return { @@ -1619,7 +1619,7 @@ export class MatrixInput extends Input { let operator = originalTree[0]; if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { // if original value was the transpose of a vector, @@ -1716,7 +1716,7 @@ export class MatrixInput extends Input { if (Array.isArray(originalTree)) { let operator = originalTree[0]; - if (operator === "vector" || operator === "altvector" || operator === "tuple") { + if (vectorOperators.includes(operator)) { // if original immediateValue was a vector, then keep it as a vector let desiredValue = me.fromAst([operator, ...desiredTree[2].slice(1).map(x => x[1])]) return { @@ -1734,7 +1734,7 @@ export class MatrixInput extends Input { let operator = originalTree[0]; if (Array.isArray(originalTree[1]) - && (originalTree[1][0] === "vector" || originalTree[1][0] === "altvector" || originalTree[1][0] === "tuple") + && vectorOperators.includes(originalTree[1][0]) && ((operator === "^" && originalTree[2] === "T") || operator === "prime") ) { // if original immediateValue was the transpose of a vector, diff --git a/src/Core/components/Point.js b/src/Core/components/Point.js index 488a151ea9..094fea22e4 100644 --- a/src/Core/components/Point.js +++ b/src/Core/components/Point.js @@ -1,6 +1,6 @@ import GraphicalComponent from './abstract/GraphicalComponent'; import me from 'math-expressions'; -import { convertValueToMathExpression, roundForDisplay } from '../utils/math'; +import { convertValueToMathExpression, roundForDisplay, vectorOperators } from '../utils/math'; import { returnBreakStringsSugarFunction } from './commonsugar/breakstrings'; import { deepClone } from '../utils/deepFunctions'; @@ -442,7 +442,7 @@ export default class Point extends GraphicalComponent { if (basedOnCoords) { let coordsTree = coords.tree; - if (Array.isArray(coordsTree) && ["tuple", "vector", "altvector"].includes(coordsTree[0])) { + if (Array.isArray(coordsTree) && vectorOperators.includes(coordsTree[0])) { nDimensions = Math.max(coordsTree.length - 1, nDimensions); } else { nDimensions = Math.max(1, nDimensions); @@ -602,7 +602,7 @@ export default class Point extends GraphicalComponent { if (basedOnCoords) { let coordsTree = coords.tree; - if (Array.isArray(coordsTree) && ["tuple", "vector", "altvector"].includes(coordsTree[0])) { + if (Array.isArray(coordsTree) && vectorOperators.includes(coordsTree[0])) { for (let arrayKey of arrayKeys) { let ind = Number(arrayKey); if (ind >= 0 || ind < coordsTree.length - 1) { @@ -952,7 +952,7 @@ export default class Point extends GraphicalComponent { let coordsTree = desiredStateVariableValues.coords.tree; - if (!(Array.isArray(coordsTree) && ["tuple", "vector", "altvector"].includes(coordsTree[0]))) { + if (!(Array.isArray(coordsTree) && vectorOperators.includes(coordsTree[0]))) { desiredXValues[0] = desiredStateVariableValues.coords; } else { for (let i = 0; i < coordsTree.length - 1; i++) { diff --git a/src/Core/components/Ray.js b/src/Core/components/Ray.js index 33685e9151..749fc8c860 100644 --- a/src/Core/components/Ray.js +++ b/src/Core/components/Ray.js @@ -1,6 +1,6 @@ import GraphicalComponent from './abstract/GraphicalComponent'; import me from 'math-expressions'; -import { convertValueToMathExpression } from '../utils/math'; +import { convertValueToMathExpression, vectorOperators } from '../utils/math'; export default class Ray extends GraphicalComponent { constructor(args) { @@ -326,7 +326,7 @@ export default class Ray extends GraphicalComponent { nDimDirection = dependencyValues.directionAttr.stateValues.nDimensions; } else if (dependencyValues.directionShadow) { let directionTree = dependencyValues.directionShadow.tree; - if (Array.isArray(directionTree) && ["tuple", "vector", "altvector"].includes(directionTree[0])) { + if (Array.isArray(directionTree) && vectorOperators.includes(directionTree[0])) { nDimDirection = directionTree.length - 1; } else { nDimDirection = 2; @@ -410,7 +410,7 @@ export default class Ray extends GraphicalComponent { nDimThrough = dependencyValues.throughAttr.stateValues.nDimensions; } else if (dependencyValues.throughShadow) { let throughTree = dependencyValues.throughShadow.tree; - if (Array.isArray(throughTree) && ["tuple", "vector", "altvector"].includes(throughTree[0])) { + if (Array.isArray(throughTree) && vectorOperators.includes(throughTree[0])) { nDimThrough = throughTree.length - 1; } else { nDimThrough = 2; @@ -494,7 +494,7 @@ export default class Ray extends GraphicalComponent { nDimEndpoint = dependencyValues.endpointAttr.stateValues.nDimensions; } else if (dependencyValues.endpointShadow) { let endpointTree = dependencyValues.endpointShadow.tree; - if (Array.isArray(endpointTree) && ["tuple", "vector", "altvector"].includes(endpointTree[0])) { + if (Array.isArray(endpointTree) && vectorOperators.includes(endpointTree[0])) { nDimEndpoint = endpointTree.length - 1; } else { nDimEndpoint = 2; diff --git a/src/Core/components/Spreadsheet.js b/src/Core/components/Spreadsheet.js index 1dfca5ccc5..0bdb7c5e50 100644 --- a/src/Core/components/Spreadsheet.js +++ b/src/Core/components/Spreadsheet.js @@ -1,6 +1,6 @@ import { normalizeIndex } from '../utils/table'; import BlockComponent from './abstract/BlockComponent'; -import { textToAst } from '../utils/math'; +import { textToAst, vectorOperators } from '../utils/math'; import me from 'math-expressions'; import { HyperFormula } from 'hyperformula'; @@ -1170,9 +1170,7 @@ export default class Spreadsheet extends BlockComponent { continue; } - if (Array.isArray(cellME.tree) && ( - cellME.tree[0] === "tuple" || cellME.tree[0] === "vector" || cellME.tree[0] === "altvector" - )) { + if (Array.isArray(cellME.tree) && vectorOperators.includes(cellME.tree[0])) { pointsInCells[arrayKey] = cellME; } else { pointsInCells[arrayKey] = null; diff --git a/src/Core/components/Vector.js b/src/Core/components/Vector.js index 9d9dbc4069..15c9227552 100644 --- a/src/Core/components/Vector.js +++ b/src/Core/components/Vector.js @@ -1,7 +1,7 @@ import GraphicalComponent from './abstract/GraphicalComponent'; import me from 'math-expressions'; import { returnBreakStringsSugarFunction } from './commonsugar/breakstrings'; -import { convertValueToMathExpression, roundForDisplay } from '../utils/math'; +import { convertValueToMathExpression, roundForDisplay, vectorOperators } from '../utils/math'; export default class Vector extends GraphicalComponent { constructor(args) { @@ -698,7 +698,7 @@ export default class Vector extends GraphicalComponent { // since based on displacement and no source of displacement // we must have a displacement shadow let displacementTree = dependencyValues.displacementShadow.tree; - if (Array.isArray(displacementTree) && ["tuple", "vector", "altvector"].includes(displacementTree[0])) { + if (Array.isArray(displacementTree) && vectorOperators.includes(displacementTree[0])) { nDimDisplacement = displacementTree.length - 1; } else { nDimDisplacement = 1; @@ -782,7 +782,7 @@ export default class Vector extends GraphicalComponent { nDimHead = dependencyValues.headAttr.stateValues.nDimensions; } else if (dependencyValues.headShadow) { let headTree = dependencyValues.headShadow.tree; - if (Array.isArray(headTree) && ["tuple", "vector", "altvector"].includes(headTree[0])) { + if (Array.isArray(headTree) && vectorOperators.includes(headTree[0])) { nDimHead = headTree.length - 1; } else { nDimHead = 2; @@ -866,7 +866,7 @@ export default class Vector extends GraphicalComponent { nDimTail = dependencyValues.tailAttr.stateValues.nDimensions; } else if (dependencyValues.tailShadow) { let tailTree = dependencyValues.tailShadow.tree; - if (Array.isArray(tailTree) && ["tuple", "vector", "altvector"].includes(tailTree[0])) { + if (Array.isArray(tailTree) && vectorOperators.includes(tailTree[0])) { nDimTail = tailTree.length - 1; } else { nDimTail = 2; @@ -1138,7 +1138,7 @@ export default class Vector extends GraphicalComponent { // since based on displacement and no source of displacement // we must have a displacement shadow let displacementTree = globalDependencyValues.displacementShadow.tree; - if (Array.isArray(displacementTree) && ["tuple", "vector", "altvector"].includes(displacementTree[0])) { + if (Array.isArray(displacementTree) && vectorOperators.includes(displacementTree[0])) { displacement[arrayKey] = globalDependencyValues.displacementShadow.get_component(Number(arrayKey)); } else { displacement[arrayKey] = globalDependencyValues.displacementShadow; @@ -1879,7 +1879,7 @@ export default class Vector extends GraphicalComponent { let coordsAst = desiredStateVariableValues.displacementCoords.tree; let newDisplacement; - if (Array.isArray(coordsAst) && (coordsAst[0] === "vector" || coordsAst[0] === "altvector" || coordsAst[0] === "tuple")) { + if (Array.isArray(coordsAst) && vectorOperators.includes(coordsAst[0])) { newDisplacement = coordsAst.slice(1).map(x => me.fromAst(x)); } else { newDisplacement = [desiredStateVariableValues.displacementCoords]; diff --git a/src/Core/utils/checkEquality.js b/src/Core/utils/checkEquality.js index 62577b8804..3c197dd67b 100644 --- a/src/Core/utils/checkEquality.js +++ b/src/Core/utils/checkEquality.js @@ -1,8 +1,10 @@ import me from 'math-expressions'; import { deepCompare } from './deepFunctions'; -import { normalizeMathExpression } from './math'; +import { normalizeMathExpression, vectorOperators } from './math'; import periodicSetEquality from './periodicSetEquality'; +const nonTupleVectorOperators = ["vector", "altvector"]; + export default function checkEquality({ object1, object2, isUnordered = false, partialMatches = false, matchByExactPositions = false, @@ -304,7 +306,7 @@ export default function checkEquality({ // a list of length 1 // make object1 act like a list of the one element object1 = [object1.tree]; - } else if (object1_operator === "vector" || object1_operator === "altvector") { + } else if (nonTupleVectorOperators.includes(object1_operator)) { // change object1 to array of elements object1 = object1.tree.slice(1); @@ -313,7 +315,7 @@ export default function checkEquality({ || object2_operator === "set" ) { return { fraction_equal: 0 }; - } else if (object2_operator === "tuple" || object2_operator === "vector" || object2_operator === "altvector") { + } else if (vectorOperators.includes(object2_operator)) { // since we can convert tuple to vector // change object2 to array of selements object2 = object2.tree.slice(1); @@ -322,7 +324,7 @@ export default function checkEquality({ // make object2 array of the one element object2 = [object2.tree]; } - } else if (object2_operator === "vector" || object2_operator === "altvector") { + } else if (nonTupleVectorOperators.includes(object2_operator)) { // change object2 to array of elements object2 = object2.tree.slice(1); diff --git a/src/Core/utils/function.js b/src/Core/utils/function.js index fea6f42ddb..789dcd1021 100644 --- a/src/Core/utils/function.js +++ b/src/Core/utils/function.js @@ -1,5 +1,5 @@ import me from 'math-expressions'; -import { convertValueToMathExpression, normalizeMathExpression } from './math'; +import { convertValueToMathExpression, normalizeMathExpression, vectorOperators } from './math'; export function createFunctionFromDefinition(fDefinition, component = 0) { @@ -60,7 +60,7 @@ export function returnNumericalFunctionFromFormula({ formula, nInputs, variables component = Number(component); let formulaIsVectorValued = Array.isArray(formula.tree) && - ["tuple", "vector", "altvector"].includes(formula.tree[0]); + vectorOperators.includes(formula.tree[0]); if (formulaIsVectorValued) { try { @@ -146,7 +146,7 @@ export function returnSymbolicFunctionFromFormula(dependencyValues, arrayKey) { let formula = dependencyValues.formula; let formulaIsVectorValued = Array.isArray(formula.tree) && - ["tuple", "vector", "altvector"].includes(formula.tree[0]); + vectorOperators.includes(formula.tree[0]); if (formulaIsVectorValued) { try { diff --git a/src/Core/utils/math.js b/src/Core/utils/math.js index 15c4378972..00f6f8b271 100644 --- a/src/Core/utils/math.js +++ b/src/Core/utils/math.js @@ -224,7 +224,7 @@ export async function preprocessMathInverseDefinition({ desiredValue, stateValues, variableName = "value", arrayKey, workspace }) { - if ((desiredValue.tree[0] !== "tuple" && desiredValue.tree[0] !== "vector" && desiredValue.tree[0] !== "altvector") + if (!vectorOperators.includes(desiredValue.tree[0]) || !desiredValue.tree.includes() ) { return { desiredValue }; @@ -252,7 +252,7 @@ export async function preprocessMathInverseDefinition({ desiredValue, currentValue = currentValue[arrayKey] } - if (currentValue && (currentValue.tree[0] === "tuple" || currentValue.tree[0] === "vector" || currentValue.tree[0] === "altvector")) { + if (currentValue && vectorOperators.includes(currentValue.tree[0])) { // if we have a currentValue that is a vector // we will merge components from desired value into current value @@ -531,7 +531,7 @@ export function mergeListsWithOtherContainers(tree) { let operator = tree[0]; let operands = tree.slice(1); - if (["tuple", "vector", "altvector", "list", "set"].includes(operator)) { + if ([...vectorOperators, "list", "set"].includes(operator)) { operands = operands.reduce((a, c) => Array.isArray(c) && c[0] === "list" ? [...a, ...c.slice(1)] : [...a, c], []) } @@ -826,4 +826,6 @@ export const mathjaxConfig = { tex2jax: { displayMath: [['\\[', '\\]']] } -}; \ No newline at end of file +}; + +export const vectorOperators = ["vector", "altvector", "tuple"]; \ No newline at end of file