From dd866be8dd4219a78f4891ed62834073089e28ed Mon Sep 17 00:00:00 2001 From: Irtaza Akram Date: Mon, 1 Dec 2025 19:59:41 +0500 Subject: [PATCH 1/2] fix: run prettier on problem block code --- .../test_files/js/mersenne-twister-min.js | 161 +- .../test_files/js/test_problem_display.js | 21 +- .../test_files/js/test_problem_generator.js | 19 +- .../test_files/js/test_problem_grader.js | 26 +- xmodule/capa/tests/test_files/js/xproblem.js | 30 +- xmodule/js/spec/capa/display_spec.js | 1009 +- xmodule/js/spec/capa/imageinput_spec.js | 248 +- xmodule/js/spec/collapsible_spec.js | 208 +- xmodule/js/spec/helper.js | 638 +- xmodule/js/src/capa/display.js | 2601 ++-- xmodule/js/src/capa/imageinput.js | 79 +- xmodule/js/src/capa/schematic.js | 12386 ++++++++-------- xmodule/js/src/collapsible.js | 226 +- xmodule/js/src/javascript_loader.js | 165 +- xmodule/js/src/problem/edit.js | 1635 +- .../ProblemBlockDisplay.css | 1045 +- .../css-builtin-blocks/ProblemBlockEditor.css | 2 +- xmodule/templates/problem/blank_common.yaml | 4 +- .../problem/checkboxes_response.yaml | 45 +- .../problem/checkboxes_response_hint.yaml | 83 +- .../templates/problem/circuitschematic.yaml | 166 +- xmodule/templates/problem/customgrader.yaml | 144 +- xmodule/templates/problem/drag_and_drop.yaml | 160 +- .../templates/problem/formularesponse.yaml | 22 +- xmodule/templates/problem/imageresponse.yaml | 56 +- .../templates/problem/jsinput_response.yaml | 132 +- xmodule/templates/problem/latex_problem.yaml | 424 +- xmodule/templates/problem/multiplechoice.yaml | 41 +- .../problem/multiplechoice_hint.yaml | 62 +- .../templates/problem/numericalresponse.yaml | 30 +- .../problem/numericalresponse_hint.yaml | 44 +- xmodule/templates/problem/optionresponse.yaml | 44 +- .../problem/optionresponse_hint.yaml | 56 +- .../templates/problem/problem_with_hint.yaml | 76 +- .../problem/problem_with_hint_in_latex.yaml | 120 +- .../templates/problem/string_response.yaml | 32 +- .../problem/string_response_hint.yaml | 50 +- 37 files changed, 11538 insertions(+), 10752 deletions(-) diff --git a/xmodule/capa/tests/test_files/js/mersenne-twister-min.js b/xmodule/capa/tests/test_files/js/mersenne-twister-min.js index f96671a634de..1a96407b35d3 100644 --- a/xmodule/capa/tests/test_files/js/mersenne-twister-min.js +++ b/xmodule/capa/tests/test_files/js/mersenne-twister-min.js @@ -65,91 +65,103 @@ */ /* eslint-disable */ -var MersenneTwister = function(seed) { +var MersenneTwister = function (seed) { if (seed == undefined) { seed = new Date().getTime(); - } - /* Period parameters */ + } + /* Period parameters */ this.N = 624; this.M = 397; - this.MATRIX_A = 0x9908b0df; /* constant vector a */ + this.MATRIX_A = 0x9908b0df; /* constant vector a */ this.UPPER_MASK = 0x80000000; /* most significant w-r bits */ this.LOWER_MASK = 0x7fffffff; /* least significant r bits */ - + this.mt = new Array(this.N); /* the array for the state vector */ - this.mti=this.N+1; /* mti==N+1 means mt[N] is not initialized */ + this.mti = this.N + 1; /* mti==N+1 means mt[N] is not initialized */ this.init_genrand(seed); -} - +}; + /* initializes mt[N] with a seed */ -MersenneTwister.prototype.init_genrand = function(s) { +MersenneTwister.prototype.init_genrand = function (s) { this.mt[0] = s >>> 0; - for (this.mti=1; this.mti>> 30); - this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253) - + this.mti; - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - this.mt[this.mti] >>>= 0; - /* for >32 bit machines */ + for (this.mti = 1; this.mti < this.N; this.mti++) { + var s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30); + this.mt[this.mti] = ((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253 + this.mti; + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + this.mt[this.mti] >>>= 0; + /* for >32 bit machines */ } -} - +}; + /* initialize by an array with array-length */ /* init_key is the array for initializing keys */ /* key_length is its length */ /* slight change for C++, 2004/2/26 */ -MersenneTwister.prototype.init_by_array = function(init_key, key_length) { +MersenneTwister.prototype.init_by_array = function (init_key, key_length) { var i, j, k; this.init_genrand(19650218); - i=1; j=0; - k = (this.N>key_length ? this.N : key_length); + i = 1; + j = 0; + k = this.N > key_length ? this.N : key_length; for (; k; k--) { - var s = this.mt[i-1] ^ (this.mt[i-1] >>> 30) - this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1664525) << 16) + ((s & 0x0000ffff) * 1664525))) - + init_key[j] + j; /* non linear */ + var s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30); + this.mt[i] = + (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1664525) << 16) + (s & 0x0000ffff) * 1664525)) + + init_key[j] + + j; /* non linear */ this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */ - i++; j++; - if (i>=this.N) { this.mt[0] = this.mt[this.N-1]; i=1; } - if (j>=key_length) j=0; + i++; + j++; + if (i >= this.N) { + this.mt[0] = this.mt[this.N - 1]; + i = 1; + } + if (j >= key_length) j = 0; } - for (k=this.N-1; k; k--) { - var s = this.mt[i-1] ^ (this.mt[i-1] >>> 30); - this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1566083941) << 16) + (s & 0x0000ffff) * 1566083941)) - - i; /* non linear */ + for (k = this.N - 1; k; k--) { + var s = this.mt[i - 1] ^ (this.mt[i - 1] >>> 30); + this.mt[i] = + (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1566083941) << 16) + (s & 0x0000ffff) * 1566083941)) - + i; /* non linear */ this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */ i++; - if (i>=this.N) { this.mt[0] = this.mt[this.N-1]; i=1; } + if (i >= this.N) { + this.mt[0] = this.mt[this.N - 1]; + i = 1; + } } - this.mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */ -} - + this.mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */ +}; + /* generates a random number on [0,0xffffffff]-interval */ -MersenneTwister.prototype.genrand_int32 = function() { +MersenneTwister.prototype.genrand_int32 = function () { var y; var mag01 = new Array(0x0, this.MATRIX_A); /* mag01[x] = x * MATRIX_A for x=0,1 */ - if (this.mti >= this.N) { /* generate N words at one time */ + if (this.mti >= this.N) { + /* generate N words at one time */ var kk; - if (this.mti == this.N+1) /* if init_genrand() has not been called, */ + if (this.mti == this.N + 1) + /* if init_genrand() has not been called, */ this.init_genrand(5489); /* a default initial seed is used */ - for (kk=0;kk>> 1) ^ mag01[y & 0x1]; + for (kk = 0; kk < this.N - this.M; kk++) { + y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK); + this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1]; } - for (;kk>> 1) ^ mag01[y & 0x1]; + for (; kk < this.N - 1; kk++) { + y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK); + this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } - y = (this.mt[this.N-1]&this.UPPER_MASK)|(this.mt[0]&this.LOWER_MASK); - this.mt[this.N-1] = this.mt[this.M-1] ^ (y >>> 1) ^ mag01[y & 0x1]; + y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK); + this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]; this.mti = 0; } @@ -157,45 +169,46 @@ MersenneTwister.prototype.genrand_int32 = function() { y = this.mt[this.mti++]; /* Tempering */ - y ^= (y >>> 11); + y ^= y >>> 11; y ^= (y << 7) & 0x9d2c5680; y ^= (y << 15) & 0xefc60000; - y ^= (y >>> 18); + y ^= y >>> 18; return y >>> 0; -} - +}; + /* generates a random number on [0,0x7fffffff]-interval */ -MersenneTwister.prototype.genrand_int31 = function() { - return (this.genrand_int32()>>>1); -} - +MersenneTwister.prototype.genrand_int31 = function () { + return this.genrand_int32() >>> 1; +}; + /* generates a random number on [0,1]-real-interval */ -MersenneTwister.prototype.genrand_real1 = function() { - return this.genrand_int32()*(1.0/4294967295.0); - /* divided by 2^32-1 */ -} +MersenneTwister.prototype.genrand_real1 = function () { + return this.genrand_int32() * (1.0 / 4294967295.0); + /* divided by 2^32-1 */ +}; /* generates a random number on [0,1)-real-interval */ -MersenneTwister.prototype.random = function() { - return this.genrand_int32()*(1.0/4294967296.0); +MersenneTwister.prototype.random = function () { + return this.genrand_int32() * (1.0 / 4294967296.0); /* divided by 2^32 */ -} - +}; + /* generates a random number on (0,1)-real-interval */ -MersenneTwister.prototype.genrand_real3 = function() { - return (this.genrand_int32() + 0.5)*(1.0/4294967296.0); +MersenneTwister.prototype.genrand_real3 = function () { + return (this.genrand_int32() + 0.5) * (1.0 / 4294967296.0); /* divided by 2^32 */ -} - +}; + /* generates a random number on [0,1) with 53-bit resolution*/ -MersenneTwister.prototype.genrand_res53 = function() { - var a=this.genrand_int32()>>>5, b=this.genrand_int32()>>>6; - return(a*67108864.0+b)*(1.0/9007199254740992.0); -} +MersenneTwister.prototype.genrand_res53 = function () { + var a = this.genrand_int32() >>> 5, + b = this.genrand_int32() >>> 6; + return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0); +}; /* These real versions are due to Isaku Wada, 2002/01/09 added */ -if(typeof exports == 'undefined'){ +if (typeof exports == "undefined") { var root = this; } else { var root = exports; diff --git a/xmodule/capa/tests/test_files/js/test_problem_display.js b/xmodule/capa/tests/test_files/js/test_problem_display.js index 2bcaaf1a415c..f6a3abefbbdf 100644 --- a/xmodule/capa/tests/test_files/js/test_problem_display.js +++ b/xmodule/capa/tests/test_files/js/test_problem_display.js @@ -8,14 +8,16 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ class MinimaxProblemDisplay extends XProblemDisplay { - constructor(state, submission, evaluation, container, submissionField, parameters) { - { // Hack: trick Babel/TypeScript into allowing this before super. - if (false) { super(); } - let thisFn = (() => { this; }).toString(); - let thisName = thisFn.slice(thisFn.indexOf('{') + 1, thisFn.indexOf(';')).trim(); + if (false) { + super(); + } + let thisFn = (() => { + this; + }).toString(); + let thisName = thisFn.slice(thisFn.indexOf("{") + 1, thisFn.indexOf(";")).trim(); eval(`${thisName} = this;`); } this.state = state; @@ -23,7 +25,9 @@ class MinimaxProblemDisplay extends XProblemDisplay { this.evaluation = evaluation; this.container = container; this.submissionField = submissionField; - if (parameters == null) { parameters = {}; } + if (parameters == null) { + parameters = {}; + } this.parameters = parameters; super(this.state, this.submission, this.evaluation, this.container, this.submissionField, this.parameters); } @@ -31,7 +35,6 @@ class MinimaxProblemDisplay extends XProblemDisplay { render() {} createSubmission() { - this.newSubmission = {}; if (this.submission != null) { @@ -39,7 +42,7 @@ class MinimaxProblemDisplay extends XProblemDisplay { const result = []; for (let id in this.submission) { const value = this.submission[id]; - result.push(this.newSubmission[id] = value); + result.push((this.newSubmission[id] = value)); } return result; })(); @@ -51,5 +54,5 @@ class MinimaxProblemDisplay extends XProblemDisplay { } } -const root = typeof exports !== 'undefined' && exports !== null ? exports : this; +const root = typeof exports !== "undefined" && exports !== null ? exports : this; root.TestProblemDisplay = TestProblemDisplay; diff --git a/xmodule/capa/tests/test_files/js/test_problem_generator.js b/xmodule/capa/tests/test_files/js/test_problem_generator.js index 4e7a795fcca4..17f8c1b5f994 100644 --- a/xmodule/capa/tests/test_files/js/test_problem_generator.js +++ b/xmodule/capa/tests/test_files/js/test_problem_generator.js @@ -6,28 +6,31 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ class TestProblemGenerator extends XProblemGenerator { - constructor(seed, parameters) { - { // Hack: trick Babel/TypeScript into allowing this before super. - if (false) { super(); } - let thisFn = (() => { this; }).toString(); - let thisName = thisFn.slice(thisFn.indexOf('{') + 1, thisFn.indexOf(';')).trim(); + if (false) { + super(); + } + let thisFn = (() => { + this; + }).toString(); + let thisName = thisFn.slice(thisFn.indexOf("{") + 1, thisFn.indexOf(";")).trim(); eval(`${thisName} = this;`); } - if (parameters == null) { parameters = {}; } + if (parameters == null) { + parameters = {}; + } this.parameters = parameters; super(seed, this.parameters); } generate() { - this.problemState.value = this.parameters.value; return this.problemState; } } -const root = typeof exports !== 'undefined' && exports !== null ? exports : this; +const root = typeof exports !== "undefined" && exports !== null ? exports : this; root.generatorClass = TestProblemGenerator; diff --git a/xmodule/capa/tests/test_files/js/test_problem_grader.js b/xmodule/capa/tests/test_files/js/test_problem_grader.js index af884bfe9d31..7f36404e1505 100644 --- a/xmodule/capa/tests/test_files/js/test_problem_grader.js +++ b/xmodule/capa/tests/test_files/js/test_problem_grader.js @@ -7,31 +7,33 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ class TestProblemGrader extends XProblemGrader { - constructor(submission, problemState, parameters) { - { // Hack: trick Babel/TypeScript into allowing this before super. - if (false) { super(); } - let thisFn = (() => { this; }).toString(); - let thisName = thisFn.slice(thisFn.indexOf('{') + 1, thisFn.indexOf(';')).trim(); + if (false) { + super(); + } + let thisFn = (() => { + this; + }).toString(); + let thisName = thisFn.slice(thisFn.indexOf("{") + 1, thisFn.indexOf(";")).trim(); eval(`${thisName} = this;`); } this.submission = submission; this.problemState = problemState; - if (parameters == null) { parameters = {}; } + if (parameters == null) { + parameters = {}; + } this.parameters = parameters; super(this.submission, this.problemState, this.parameters); } solve() { - - return this.solution = {0: this.problemState.value}; + return (this.solution = { 0: this.problemState.value }); } grade() { - - if ((this.solution == null)) { + if (this.solution == null) { this.solve(); } @@ -39,7 +41,7 @@ class TestProblemGrader extends XProblemGrader { for (let id in this.solution) { const value = this.solution[id]; - const valueCorrect = (this.submission != null) ? (value === this.submission[id]) : false; + const valueCorrect = this.submission != null ? value === this.submission[id] : false; this.evaluation[id] = valueCorrect; if (!valueCorrect) { allCorrect = false; @@ -50,5 +52,5 @@ class TestProblemGrader extends XProblemGrader { } } -const root = typeof exports !== 'undefined' && exports !== null ? exports : this; +const root = typeof exports !== "undefined" && exports !== null ? exports : this; root.graderClass = TestProblemGrader; diff --git a/xmodule/capa/tests/test_files/js/xproblem.js b/xmodule/capa/tests/test_files/js/xproblem.js index e3d39dd34f01..b2df386f1183 100644 --- a/xmodule/capa/tests/test_files/js/xproblem.js +++ b/xmodule/capa/tests/test_files/js/xproblem.js @@ -5,10 +5,10 @@ * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ class XProblemGenerator { - constructor(seed, parameters) { - - if (parameters == null) { parameters = {}; } + if (parameters == null) { + parameters = {}; + } this.parameters = parameters; this.random = new MersenneTwister(seed); @@ -16,30 +16,28 @@ class XProblemGenerator { } generate() { - console.error("Abstract method called: XProblemGenerator.generate"); } } class XProblemDisplay { - constructor(state, submission, evaluation, container, submissionField, parameters) { this.state = state; this.submission = submission; this.evaluation = evaluation; this.container = container; this.submissionField = submissionField; - if (parameters == null) { parameters = {}; } + if (parameters == null) { + parameters = {}; + } this.parameters = parameters; } render() { - console.error("Abstract method called: XProblemDisplay.render"); } updateSubmission() { - this.submissionField.val(JSON.stringify(this.getCurrentSubmission())); } @@ -49,30 +47,28 @@ class XProblemDisplay { } class XProblemGrader { - constructor(submission, problemState, parameters) { - this.submission = submission; this.problemState = problemState; - if (parameters == null) { parameters = {}; } + if (parameters == null) { + parameters = {}; + } this.parameters = parameters; - this.solution = null; + this.solution = null; this.evaluation = {}; } solve() { - console.error("Abstract method called: XProblemGrader.solve"); } grade() { - console.error("Abstract method called: XProblemGrader.grade"); } } -const root = typeof exports !== 'undefined' && exports !== null ? exports : this; +const root = typeof exports !== "undefined" && exports !== null ? exports : this; root.XProblemGenerator = XProblemGenerator; -root.XProblemDisplay = XProblemDisplay; -root.XProblemGrader = XProblemGrader; +root.XProblemDisplay = XProblemDisplay; +root.XProblemGrader = XProblemGrader; diff --git a/xmodule/js/spec/capa/display_spec.js b/xmodule/js/spec/capa/display_spec.js index 385bd2d24333..f55106f31758 100644 --- a/xmodule/js/spec/capa/display_spec.js +++ b/xmodule/js/spec/capa/display_spec.js @@ -4,20 +4,20 @@ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -describe('Problem', function() { - const problem_content_default = readFixtures('problem_content.html'); +describe("Problem", function () { + const problem_content_default = readFixtures("problem_content.html"); - beforeEach(function() { + beforeEach(function () { // Stub MathJax window.MathJax = { - Hub: jasmine.createSpyObj('MathJax.Hub', ['getAllJax', 'Queue']), - Callback: jasmine.createSpyObj('MathJax.Callback', ['After']) + Hub: jasmine.createSpyObj("MathJax.Hub", ["getAllJax", "Queue"]), + Callback: jasmine.createSpyObj("MathJax.Callback", ["After"]), }; - this.stubbedJax = {root: jasmine.createSpyObj('jax.root', ['toMathML'])}; + this.stubbedJax = { root: jasmine.createSpyObj("jax.root", ["toMathML"]) }; MathJax.Hub.getAllJax.and.returnValue([this.stubbedJax]); - window.update_schematics = function() {}; - spyOn(SR, 'readText'); - spyOn(SR, 'readTexts'); + window.update_schematics = function () {}; + spyOn(SR, "readText"); + spyOn(SR, "readTexts"); // Load this function from spec/helper.js // Note that if your test fails with a message like: @@ -25,19 +25,18 @@ describe('Problem', function() { // this msg is coming from the stubRequests function else clause. jasmine.stubRequests(); - loadFixtures('problem.html'); + loadFixtures("problem.html"); - spyOn(Logger, 'log'); - spyOn($.fn, 'load').and.callFake(function(url, callback) { - $(this).html(readFixtures('problem_content.html')); + spyOn(Logger, "log"); + spyOn($.fn, "load").and.callFake(function (url, callback) { + $(this).html(readFixtures("problem_content.html")); return callback(); }); }); - describe('constructor', function() { - - it('set the element from html', function() { - this.problem999 = new Problem((`\ + describe("constructor", function () { + it("set the element from html", function () { + this.problem999 = new Problem(`\
\
\
\
\ -`) - ); - expect(this.problem999.element_id).toBe('problem_999'); +`); + expect(this.problem999.element_id).toBe("problem_999"); }); - it('set the element from loadFixtures', function() { - this.problem1 = new Problem($('.xblock-student_view')); - expect(this.problem1.element_id).toBe('problem_1'); + it("set the element from loadFixtures", function () { + this.problem1 = new Problem($(".xblock-student_view")); + expect(this.problem1.element_id).toBe("problem_1"); }); }); - describe('bind', function() { - beforeEach(function() { - spyOn(window, 'update_schematics'); + describe("bind", function () { + beforeEach(function () { + spyOn(window, "update_schematics"); MathJax.Hub.getAllJax.and.returnValue([this.stubbedJax]); - this.problem = new Problem($('.xblock-student_view')); + this.problem = new Problem($(".xblock-student_view")); }); - it('set mathjax typeset', () => expect(MathJax.Hub.Queue).toHaveBeenCalled()); + it("set mathjax typeset", () => expect(MathJax.Hub.Queue).toHaveBeenCalled()); - it('update schematics', () => expect(window.update_schematics).toHaveBeenCalled()); + it("update schematics", () => expect(window.update_schematics).toHaveBeenCalled()); - it('bind answer refresh on button click', function() { - expect($('div.action button')).toHandleWith('click', this.problem.refreshAnswers); + it("bind answer refresh on button click", function () { + expect($("div.action button")).toHandleWith("click", this.problem.refreshAnswers); }); - it('bind the submit button', function() { - expect($('.action .submit')).toHandleWith('click', this.problem.submit_fd); + it("bind the submit button", function () { + expect($(".action .submit")).toHandleWith("click", this.problem.submit_fd); }); - it('bind the reset button', function() { - expect($('div.action button.reset')).toHandleWith('click', this.problem.reset); + it("bind the reset button", function () { + expect($("div.action button.reset")).toHandleWith("click", this.problem.reset); }); - it('bind the show button', function() { - expect($('.action .show')).toHandleWith('click', this.problem.show); + it("bind the show button", function () { + expect($(".action .show")).toHandleWith("click", this.problem.show); }); - it('bind the save button', function() { - expect($('div.action button.save')).toHandleWith('click', this.problem.save); + it("bind the save button", function () { + expect($("div.action button.save")).toHandleWith("click", this.problem.save); }); - it('bind the math input', function() { - expect($('input.math')).toHandleWith('keyup', this.problem.refreshMath); + it("bind the math input", function () { + expect($("input.math")).toHandleWith("keyup", this.problem.refreshMath); }); }); - describe('bind_with_custom_input_id', function() { - beforeEach(function() { - spyOn(window, 'update_schematics'); + describe("bind_with_custom_input_id", function () { + beforeEach(function () { + spyOn(window, "update_schematics"); MathJax.Hub.getAllJax.and.returnValue([this.stubbedJax]); - this.problem = new Problem($('.xblock-student_view')); - return $(this).html(readFixtures('problem_content_1240.html')); + this.problem = new Problem($(".xblock-student_view")); + return $(this).html(readFixtures("problem_content_1240.html")); }); - it('bind the submit button', function() { - expect($('.action .submit')).toHandleWith('click', this.problem.submit_fd); + it("bind the submit button", function () { + expect($(".action .submit")).toHandleWith("click", this.problem.submit_fd); }); - it('bind the show button', function() { - expect($('div.action button.show')).toHandleWith('click', this.problem.show); + it("bind the show button", function () { + expect($("div.action button.show")).toHandleWith("click", this.problem.show); }); }); - - describe('renderProgressState', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); - }); - - const testProgessData = function(problem, score, total_possible, attempts, graded, expected_progress_after_render) { - problem.el.data('problem-score', score); - problem.el.data('problem-total-possible', total_possible); - problem.el.data('attempts-used', attempts); - problem.el.data('graded', graded); - expect(problem.$('.problem-progress').html()).toEqual(""); + describe("renderProgressState", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); + }); + + const testProgessData = function ( + problem, + score, + total_possible, + attempts, + graded, + expected_progress_after_render, + ) { + problem.el.data("problem-score", score); + problem.el.data("problem-total-possible", total_possible); + problem.el.data("attempts-used", attempts); + problem.el.data("graded", graded); + expect(problem.$(".problem-progress").html()).toEqual(""); problem.renderProgressState(); - expect(problem.$('.problem-progress').html()).toEqual(expected_progress_after_render); + expect(problem.$(".problem-progress").html()).toEqual(expected_progress_after_render); }; - describe('with a status of "none"', function() { - it('reports the number of points possible and graded', function() { + describe('with a status of "none"', function () { + it("reports the number of points possible and graded", function () { testProgessData(this.problem, 0, 1, 0, "True", "1 point possible (graded)"); }); - it('displays the number of points possible when rendering happens with the content', function() { + it("displays the number of points possible when rendering happens with the content", function () { testProgessData(this.problem, 0, 2, 0, "True", "2 points possible (graded)"); }); - it('reports the number of points possible and ungraded', function() { + it("reports the number of points possible and ungraded", function () { testProgessData(this.problem, 0, 1, 0, "False", "1 point possible (ungraded)"); }); - it('displays ungraded if number of points possible is 0', function() { + it("displays ungraded if number of points possible is 0", function () { testProgessData(this.problem, 0, 0, 0, "False", "0 points possible (ungraded)"); }); - it('displays ungraded if number of points possible is 0, even if graded value is True', function() { + it("displays ungraded if number of points possible is 0, even if graded value is True", function () { testProgessData(this.problem, 0, 0, 0, "True", "0 points possible (ungraded)"); }); - it('reports the correct score with status none and >0 attempts', function() { + it("reports the correct score with status none and >0 attempts", function () { testProgessData(this.problem, 0, 1, 1, "True", "0/1 point (graded)"); }); - it('reports the correct score with >1 weight, status none, and >0 attempts', function() { + it("reports the correct score with >1 weight, status none, and >0 attempts", function () { testProgessData(this.problem, 0, 2, 2, "True", "0/2 points (graded)"); }); }); - describe('with any other valid status', function() { - - it('reports the current score', function() { + describe("with any other valid status", function () { + it("reports the current score", function () { testProgessData(this.problem, 1, 1, 1, "True", "1/1 point (graded)"); }); - it('shows current score when rendering happens with the content', function() { + it("shows current score when rendering happens with the content", function () { testProgessData(this.problem, 2, 2, 1, "True", "2/2 points (graded)"); }); - it('reports the current score even if problem is ungraded', function() { + it("reports the current score even if problem is ungraded", function () { testProgessData(this.problem, 1, 1, 1, "False", "1/1 point (ungraded)"); }); }); describe('with valid status and string containing an integer like "0" for detail', () => // These tests are to address a failure specific to Chrome 51 and 52 + - it('shows 0 points possible for the detail', function() { + it("shows 0 points possible for the detail", function () { testProgessData(this.problem, 0, 0, 1, "False", "0 points possible (ungraded)"); - }) - ); + })); - describe('with a score of null (show_correctness == false)', function() { - it('reports the number of points possible and graded, results hidden', function() { + describe("with a score of null (show_correctness == false)", function () { + it("reports the number of points possible and graded, results hidden", function () { testProgessData(this.problem, null, 1, 0, "True", "1 point possible (graded, results hidden)"); }); - it('reports the number of points possible (plural) and graded, results hidden', function() { + it("reports the number of points possible (plural) and graded, results hidden", function () { testProgessData(this.problem, null, 2, 0, "True", "2 points possible (graded, results hidden)"); }); - it('reports the number of points possible and ungraded, results hidden', function() { + it("reports the number of points possible and ungraded, results hidden", function () { testProgessData(this.problem, null, 1, 0, "False", "1 point possible (ungraded, results hidden)"); }); - it('displays ungraded if number of points possible is 0, results hidden', function() { + it("displays ungraded if number of points possible is 0, results hidden", function () { testProgessData(this.problem, null, 0, 0, "False", "0 points possible (ungraded, results hidden)"); }); - it('displays ungraded if number of points possible is 0, even if graded value is True, results hidden', function() { + it("displays ungraded if number of points possible is 0, even if graded value is True, results hidden", function () { testProgessData(this.problem, null, 0, 0, "True", "0 points possible (ungraded, results hidden)"); }); - it('reports the correct score with status none and >0 attempts, results hidden', function() { + it("reports the correct score with status none and >0 attempts, results hidden", function () { testProgessData(this.problem, null, 1, 1, "True", "1 point possible (graded, results hidden)"); }); - it('reports the correct score with >1 weight, status none, and >0 attempts, results hidden', function() { + it("reports the correct score with >1 weight, status none, and >0 attempts, results hidden", function () { testProgessData(this.problem, null, 2, 2, "True", "2 points possible (graded, results hidden)"); }); }); }); - describe('render', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); + describe("render", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); this.bind = this.problem.bind; - spyOn(this.problem, 'bind'); + spyOn(this.problem, "bind"); }); - describe('with content given', function() { - beforeEach(function() { - this.problem.render('Hello World'); + describe("with content given", function () { + beforeEach(function () { + this.problem.render("Hello World"); }); - it('render the content', function() { - expect(this.problem.el.html()).toEqual('Hello World'); + it("render the content", function () { + expect(this.problem.el.html()).toEqual("Hello World"); }); - it('re-bind the content', function() { + it("re-bind the content", function () { expect(this.problem.bind).toHaveBeenCalled(); }); }); - describe('with no content given', function() { - beforeEach(function() { - spyOn($, 'postWithPrefix').and.callFake((url, callback) => callback({html: "Hello World"})); + describe("with no content given", function () { + beforeEach(function () { + spyOn($, "postWithPrefix").and.callFake((url, callback) => callback({ html: "Hello World" })); this.problem.render(); }); - it('load the content via ajax', function() { - expect(this.problem.el.html()).toEqual('Hello World'); + it("load the content via ajax", function () { + expect(this.problem.el.html()).toEqual("Hello World"); }); - it('re-bind the content', function() { + it("re-bind the content", function () { expect(this.problem.bind).toHaveBeenCalled(); }); }); }); - describe('submit_fd', function() { - beforeEach(function() { + describe("submit_fd", function () { + beforeEach(function () { // Insert an input of type file outside of the problem. - $('.xblock-student_view').after(''); - this.problem = new Problem($('.xblock-student_view')); - spyOn(this.problem, 'submit'); + $(".xblock-student_view").after(''); + this.problem = new Problem($(".xblock-student_view")); + spyOn(this.problem, "submit"); }); - it('submit method is called if input of type file is not in problem', function() { + it("submit method is called if input of type file is not in problem", function () { this.problem.submit_fd(); expect(this.problem.submit).toHaveBeenCalled(); }); }); - describe('submit', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); - this.problem.answers = 'foo=1&bar=2'; + describe("submit", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); + this.problem.answers = "foo=1&bar=2"; }); - it('log the problem_check event', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("log the problem_check event", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; promise = { - always(callable) { return callable(); }, - done(callable) { return callable(); } + always(callable) { + return callable(); + }, + done(callable) { + return callable(); + }, }; return promise; }); this.problem.submit(); - expect(Logger.log).toHaveBeenCalledWith('problem_check', 'foo=1&bar=2'); + expect(Logger.log).toHaveBeenCalledWith("problem_check", "foo=1&bar=2"); }); - it('log the problem_graded event, after the problem is done grading.', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("log the problem_graded event, after the problem is done grading.", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; const response = { - success: 'correct', - contents: 'mock grader response' + success: "correct", + contents: "mock grader response", }; callback(response); promise = { - always(callable) { return callable(); }, - done(callable) { return callable(); } + always(callable) { + return callable(); + }, + done(callable) { + return callable(); + }, }; return promise; }); this.problem.submit(); - expect(Logger.log).toHaveBeenCalledWith('problem_graded', ['foo=1&bar=2', 'mock grader response'], this.problem.id); + expect(Logger.log).toHaveBeenCalledWith( + "problem_graded", + ["foo=1&bar=2", "mock grader response"], + this.problem.id, + ); }); - it('submit the answer for submit', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("submit the answer for submit", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; promise = { - always(callable) { return callable(); }, - done(callable) { return callable(); } + always(callable) { + return callable(); + }, + done(callable) { + return callable(); + }, }; return promise; }); this.problem.submit(); - expect($.postWithPrefix).toHaveBeenCalledWith('/problem/Problem1/problem_check', - 'foo=1&bar=2', jasmine.any(Function)); + expect($.postWithPrefix).toHaveBeenCalledWith( + "/problem/Problem1/problem_check", + "foo=1&bar=2", + jasmine.any(Function), + ); }); - describe('when the response is correct', () => - it('call render with returned content', function() { - const contents = '

Correctexcellent

' + - '

Yepcorrect

'; - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + describe("when the response is correct", () => + it("call render with returned content", function () { + const contents = + '

Correctexcellent

' + + '

Yepcorrect

'; + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - callback({success: 'correct', contents}); + callback({ success: "correct", contents }); promise = { - always(callable) { return callable(); }, - done(callable) { return callable(); } + always(callable) { + return callable(); + }, + done(callable) { + return callable(); + }, }; return promise; }); this.problem.submit(); expect(this.problem.el).toHaveHtml(contents); - expect(window.SR.readTexts).toHaveBeenCalledWith(['Question 1: excellent', 'Question 2: correct']); - }) - ); + expect(window.SR.readTexts).toHaveBeenCalledWith(["Question 1: excellent", "Question 2: correct"]); + })); - describe('when the response is incorrect', () => - it('call render with returned content', function() { + describe("when the response is incorrect", () => + it("call render with returned content", function () { const contents = '

Incorrectno, try again

'; - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - callback({success: 'incorrect', contents}); + callback({ success: "incorrect", contents }); promise = { - always(callable) { return callable(); }, - done(callable) { return callable(); } + always(callable) { + return callable(); + }, + done(callable) { + return callable(); + }, }; return promise; }); this.problem.submit(); expect(this.problem.el).toHaveHtml(contents); - expect(window.SR.readTexts).toHaveBeenCalledWith(['no, try again']); - }) - ); + expect(window.SR.readTexts).toHaveBeenCalledWith(["no, try again"]); + })); - it('tests if the submit button is disabled while submitting and the text changes on the button', function() { + it("tests if the submit button is disabled while submitting and the text changes on the button", function () { const self = this; const curr_html = this.problem.el.html(); - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { // At this point enableButtons should have been called, making the submit button disabled with text 'submitting' let promise; - expect(self.problem.submitButton).toHaveAttr('disabled'); - expect(self.problem.submitButtonLabel.text()).toBe('Submitting'); + expect(self.problem.submitButton).toHaveAttr("disabled"); + expect(self.problem.submitButtonLabel.text()).toBe("Submitting"); callback({ - success: 'incorrect', // does not matter if correct or incorrect here - contents: curr_html + success: "incorrect", // does not matter if correct or incorrect here + contents: curr_html, }); promise = { - always(callable) { return callable(); }, - done(callable) { return callable(); } + always(callable) { + return callable(); + }, + done(callable) { + return callable(); + }, }; return promise; }); // Make sure the submit button is enabled before submitting - $('#input_example_1').val('test').trigger('input'); - expect(this.problem.submitButton).not.toHaveAttr('disabled'); + $("#input_example_1").val("test").trigger("input"); + expect(this.problem.submitButton).not.toHaveAttr("disabled"); this.problem.submit(); // After submit, the button should not be disabled and should have text as 'Submit' - expect(this.problem.submitButtonLabel.text()).toBe('Submit'); - expect(this.problem.submitButton).not.toHaveAttr('disabled'); + expect(this.problem.submitButtonLabel.text()).toBe("Submit"); + expect(this.problem.submitButton).not.toHaveAttr("disabled"); }); }); - describe('submit button on problems', function() { - - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); - this.submitDisabled = disabled => { + describe("submit button on problems", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); + this.submitDisabled = (disabled) => { if (disabled) { - expect(this.problem.submitButton).toHaveAttr('disabled'); + expect(this.problem.submitButton).toHaveAttr("disabled"); } else { - expect(this.problem.submitButton).not.toHaveAttr('disabled'); + expect(this.problem.submitButton).not.toHaveAttr("disabled"); } }; }); - describe('some basic tests for submit button', () => - it('should become enabled after a value is entered into the text box', function() { - $('#input_example_1').val('test').trigger('input'); + describe("some basic tests for submit button", () => + it("should become enabled after a value is entered into the text box", function () { + $("#input_example_1").val("test").trigger("input"); this.submitDisabled(false); - $('#input_example_1').val('').trigger('input'); + $("#input_example_1").val("").trigger("input"); this.submitDisabled(true); - }) - ); + })); - describe('some advanced tests for submit button', function() { - const radioButtonProblemHtml = readFixtures('radiobutton_problem.html'); - const checkboxProblemHtml = readFixtures('checkbox_problem.html'); + describe("some advanced tests for submit button", function () { + const radioButtonProblemHtml = readFixtures("radiobutton_problem.html"); + const checkboxProblemHtml = readFixtures("checkbox_problem.html"); - it('should become enabled after a checkbox is checked', function() { - $('#input_example_1').replaceWith(checkboxProblemHtml); + it("should become enabled after a checkbox is checked", function () { + $("#input_example_1").replaceWith(checkboxProblemHtml); this.problem.submitAnswersAndSubmitButton(true); this.submitDisabled(true); - $('#input_1_1_1').click(); + $("#input_1_1_1").click(); this.submitDisabled(false); - $('#input_1_1_1').click(); + $("#input_1_1_1").click(); this.submitDisabled(true); }); - it('should become enabled after a radiobutton is checked', function() { - $('#input_example_1').replaceWith(radioButtonProblemHtml); + it("should become enabled after a radiobutton is checked", function () { + $("#input_example_1").replaceWith(radioButtonProblemHtml); this.problem.submitAnswersAndSubmitButton(true); this.submitDisabled(true); - $('#input_1_1_1').attr('checked', true).trigger('click'); + $("#input_1_1_1").attr("checked", true).trigger("click"); this.submitDisabled(false); - $('#input_1_1_1').attr('checked', false).trigger('click'); + $("#input_1_1_1").attr("checked", false).trigger("click"); this.submitDisabled(true); }); - it('should become enabled after a value is selected in a selector', function() { + it("should become enabled after a value is selected in a selector", function () { const html = `\
\ `; - $('#input_example_1').replaceWith(html); + $("#input_example_1").replaceWith(html); this.problem.submitAnswersAndSubmitButton(true); this.submitDisabled(true); - $("#problem_sel select").val("val2").trigger('change'); + $("#problem_sel select").val("val2").trigger("change"); this.submitDisabled(false); - $("#problem_sel select").val("val0").trigger('change'); + $("#problem_sel select").val("val0").trigger("change"); this.submitDisabled(true); }); - it('should become enabled after a radiobutton is checked and a value is entered into the text box', function() { - $(radioButtonProblemHtml).insertAfter('#input_example_1'); + it("should become enabled after a radiobutton is checked and a value is entered into the text box", function () { + $(radioButtonProblemHtml).insertAfter("#input_example_1"); this.problem.submitAnswersAndSubmitButton(true); this.submitDisabled(true); - $('#input_1_1_1').attr('checked', true).trigger('click'); + $("#input_1_1_1").attr("checked", true).trigger("click"); this.submitDisabled(true); - $('#input_example_1').val('111').trigger('input'); + $("#input_example_1").val("111").trigger("input"); this.submitDisabled(false); - $('#input_1_1_1').attr('checked', false).trigger('click'); + $("#input_1_1_1").attr("checked", false).trigger("click"); this.submitDisabled(true); }); - it('should become enabled if there are only hidden input fields', function() { + it("should become enabled if there are only hidden input fields", function () { const html = `\ \ `; - $('#input_example_1').replaceWith(html); + $("#input_example_1").replaceWith(html); this.problem.submitAnswersAndSubmitButton(true); this.submitDisabled(false); }); }); }); - describe('reset', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); + describe("reset", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); }); - it('log the problem_reset event', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("log the problem_reset event", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - promise = - {always(callable) { return callable(); }}; + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); - this.problem.answers = 'foo=1&bar=2'; + this.problem.answers = "foo=1&bar=2"; this.problem.reset(); - expect(Logger.log).toHaveBeenCalledWith('problem_reset', 'foo=1&bar=2'); + expect(Logger.log).toHaveBeenCalledWith("problem_reset", "foo=1&bar=2"); }); - it('POST to the problem reset page', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("POST to the problem reset page", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - promise = - {always(callable) { return callable(); }}; + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); this.problem.reset(); - expect($.postWithPrefix).toHaveBeenCalledWith('/problem/Problem1/problem_reset', - { id: 'i4x://edX/101/problem/Problem1' }, jasmine.any(Function)); + expect($.postWithPrefix).toHaveBeenCalledWith( + "/problem/Problem1/problem_reset", + { id: "i4x://edX/101/problem/Problem1" }, + jasmine.any(Function), + ); }); - it('render the returned content', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("render the returned content", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - callback({html: "Reset", success: true}); - promise = - {always(callable) { return callable(); }}; + callback({ html: "Reset", success: true }); + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); this.problem.reset(); - expect(this.problem.el.html()).toEqual('Reset'); + expect(this.problem.el.html()).toEqual("Reset"); }); - it('sends a message to the window SR element', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("sends a message to the window SR element", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - callback({html: "Reset", success: true}); - promise = - {always(callable) { return callable(); }}; + callback({ html: "Reset", success: true }); + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); this.problem.reset(); - expect(window.SR.readText).toHaveBeenCalledWith('This problem has been reset.'); + expect(window.SR.readText).toHaveBeenCalledWith("This problem has been reset."); }); - it('shows a notification on error', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("shows a notification on error", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - callback({msg: "Error on reset.", success: false}); - promise = - {always(callable) { return callable(); }}; + callback({ msg: "Error on reset.", success: false }); + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); this.problem.reset(); - expect($('.notification-gentle-alert .notification-message').text()).toEqual("Error on reset."); + expect($(".notification-gentle-alert .notification-message").text()).toEqual("Error on reset."); }); - it('tests that reset does not enable submit or modify the text while resetting', function() { + it("tests that reset does not enable submit or modify the text while resetting", function () { const self = this; const curr_html = this.problem.el.html(); - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { // enableButtons should have been called at this point to set them to all disabled let promise; - expect(self.problem.submitButton).toHaveAttr('disabled'); - expect(self.problem.submitButtonLabel.text()).toBe('Submit'); - callback({success: 'correct', html: curr_html}); - promise = - {always(callable) { return callable(); }}; + expect(self.problem.submitButton).toHaveAttr("disabled"); + expect(self.problem.submitButtonLabel.text()).toBe("Submit"); + callback({ success: "correct", html: curr_html }); + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); // Submit should be disabled - expect(this.problem.submitButton).toHaveAttr('disabled'); + expect(this.problem.submitButton).toHaveAttr("disabled"); this.problem.reset(); // Submit should remain disabled - expect(self.problem.submitButton).toHaveAttr('disabled'); - expect(self.problem.submitButtonLabel.text()).toBe('Submit'); + expect(self.problem.submitButton).toHaveAttr("disabled"); + expect(self.problem.submitButtonLabel.text()).toBe("Submit"); }); }); - describe('show problem with column in id', function() { + describe("show problem with column in id", function () { beforeEach(function () { - this.problem = new Problem($('.xblock-student_view')); + this.problem = new Problem($(".xblock-student_view")); this.problem.el.prepend('
'); }); - it('log the problem_show event', function() { + it("log the problem_show event", function () { this.problem.show(); - expect(Logger.log).toHaveBeenCalledWith('problem_show', - {problem: 'i4x://edX/101/problem/Problem1'}); + expect(Logger.log).toHaveBeenCalledWith("problem_show", { problem: "i4x://edX/101/problem/Problem1" }); }); - it('fetch the answers', function() { - spyOn($, 'postWithPrefix'); + it("fetch the answers", function () { + spyOn($, "postWithPrefix"); this.problem.show(); - expect($.postWithPrefix).toHaveBeenCalledWith('/problem/Problem1/problem_show', - jasmine.any(Function)); + expect($.postWithPrefix).toHaveBeenCalledWith("/problem/Problem1/problem_show", jasmine.any(Function)); }); - it('show the answers', function() { - spyOn($, 'postWithPrefix').and.callFake( - (url, callback) => callback({answers: {'1_1:11': 'One', '1_2:12': 'Two'}}) + it("show the answers", function () { + spyOn($, "postWithPrefix").and.callFake((url, callback) => + callback({ answers: { "1_1:11": "One", "1_2:12": "Two" } }), ); this.problem.show(); - expect($("#answer_1_1\\:11")).toHaveHtml('One'); - expect($("#answer_1_2\\:12")).toHaveHtml('Two'); + expect($("#answer_1_1\\:11")).toHaveHtml("One"); + expect($("#answer_1_2\\:12")).toHaveHtml("Two"); }); - it('disables the show answer button', function() { - spyOn($, 'postWithPrefix').and.callFake((url, callback) => callback({answers: {}})); + it("disables the show answer button", function () { + spyOn($, "postWithPrefix").and.callFake((url, callback) => callback({ answers: {} })); this.problem.show(); - expect(this.problem.el.find('.show').attr('disabled')).toEqual('disabled'); + expect(this.problem.el.find(".show").attr("disabled")).toEqual("disabled"); }); }); - describe('show', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); + describe("show", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); this.problem.el.prepend('
'); }); - describe('when the answer has not yet shown', function() { - beforeEach(function() { - expect(this.problem.el.find('.show').attr('disabled')).not.toEqual('disabled'); + describe("when the answer has not yet shown", function () { + beforeEach(function () { + expect(this.problem.el.find(".show").attr("disabled")).not.toEqual("disabled"); }); - it('log the problem_show event', function() { + it("log the problem_show event", function () { this.problem.show(); - expect(Logger.log).toHaveBeenCalledWith('problem_show', - {problem: 'i4x://edX/101/problem/Problem1'}); + expect(Logger.log).toHaveBeenCalledWith("problem_show", { problem: "i4x://edX/101/problem/Problem1" }); }); - it('fetch the answers', function() { - spyOn($, 'postWithPrefix'); + it("fetch the answers", function () { + spyOn($, "postWithPrefix"); this.problem.show(); - expect($.postWithPrefix).toHaveBeenCalledWith('/problem/Problem1/problem_show', - jasmine.any(Function)); + expect($.postWithPrefix).toHaveBeenCalledWith("/problem/Problem1/problem_show", jasmine.any(Function)); }); - it('show the answers', function() { - spyOn($, 'postWithPrefix').and.callFake((url, callback) => callback({answers: {'1_1': 'One', '1_2': 'Two'}})); + it("show the answers", function () { + spyOn($, "postWithPrefix").and.callFake((url, callback) => + callback({ answers: { "1_1": "One", "1_2": "Two" } }), + ); this.problem.show(); - expect($('#answer_1_1')).toHaveHtml('One'); - expect($('#answer_1_2')).toHaveHtml('Two'); + expect($("#answer_1_1")).toHaveHtml("One"); + expect($("#answer_1_2")).toHaveHtml("Two"); }); - it('disables the show answer button', function() { - spyOn($, 'postWithPrefix').and.callFake((url, callback) => callback({answers: {}})); + it("disables the show answer button", function () { + spyOn($, "postWithPrefix").and.callFake((url, callback) => callback({ answers: {} })); this.problem.show(); - expect(this.problem.el.find('.show').attr('disabled')).toEqual('disabled'); + expect(this.problem.el.find(".show").attr("disabled")).toEqual("disabled"); }); - describe('radio text question', function() { - const radio_text_xml=`\ + describe("radio text question", function () { + const radio_text_xml = `\

@@ -650,44 +699,47 @@ data-url='/problem/quiz/'> \
\ `; - beforeEach(function() { + beforeEach(function () { // Append a radiotextresponse problem to the problem, so we can check it's javascript functionality this.problem.el.prepend(radio_text_xml); }); - it('sets the correct class on the section for the correct choice', function() { - spyOn($, 'postWithPrefix').and.callFake((url, callback) => callback({answers: {"1_2_1": ["1_2_1_choiceinput_0bc"], "1_2_1_choiceinput_0bc": "3"}})); + it("sets the correct class on the section for the correct choice", function () { + spyOn($, "postWithPrefix").and.callFake((url, callback) => + callback({ answers: { "1_2_1": ["1_2_1_choiceinput_0bc"], "1_2_1_choiceinput_0bc": "3" } }), + ); this.problem.show(); - expect($('#forinput1_2_1_choiceinput_0bc').attr('class')).toEqual( - 'choicetextgroup_show_correct'); - expect($('#answer_1_2_1_choiceinput_0bc').text()).toEqual('3'); - expect($('#answer_1_2_1_choiceinput_1bc').text()).toEqual(''); - expect($('#answer_1_2_1_choiceinput_2bc').text()).toEqual(''); + expect($("#forinput1_2_1_choiceinput_0bc").attr("class")).toEqual("choicetextgroup_show_correct"); + expect($("#answer_1_2_1_choiceinput_0bc").text()).toEqual("3"); + expect($("#answer_1_2_1_choiceinput_1bc").text()).toEqual(""); + expect($("#answer_1_2_1_choiceinput_2bc").text()).toEqual(""); }); - it('Should not disable input fields', function() { - spyOn($, 'postWithPrefix').and.callFake((url, callback) => callback({answers: {"1_2_1": ["1_2_1_choiceinput_0bc"], "1_2_1_choiceinput_0bc": "3"}})); + it("Should not disable input fields", function () { + spyOn($, "postWithPrefix").and.callFake((url, callback) => + callback({ answers: { "1_2_1": ["1_2_1_choiceinput_0bc"], "1_2_1_choiceinput_0bc": "3" } }), + ); this.problem.show(); - expect($('input#1_2_1_choiceinput_0bc').attr('disabled')).not.toEqual('disabled'); - expect($('input#1_2_1_choiceinput_1bc').attr('disabled')).not.toEqual('disabled'); - expect($('input#1_2_1_choiceinput_2bc').attr('disabled')).not.toEqual('disabled'); - expect($('input#1_2_1').attr('disabled')).not.toEqual('disabled'); + expect($("input#1_2_1_choiceinput_0bc").attr("disabled")).not.toEqual("disabled"); + expect($("input#1_2_1_choiceinput_1bc").attr("disabled")).not.toEqual("disabled"); + expect($("input#1_2_1_choiceinput_2bc").attr("disabled")).not.toEqual("disabled"); + expect($("input#1_2_1").attr("disabled")).not.toEqual("disabled"); }); }); - describe('imageinput', function() { + describe("imageinput", function () { let el, height, width; - const imageinput_html = readFixtures('imageinput.underscore'); + const imageinput_html = readFixtures("imageinput.underscore"); const DEFAULTS = { - id: '12345', - width: '300', - height: '400' + id: "12345", + width: "300", + height: "400", }; - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); this.problem.el.prepend(_.template(imageinput_html)(DEFAULTS)); }); @@ -695,23 +747,23 @@ data-url='/problem/quiz/'> \ stubRequest(data); problem.show(); - $.each(data['answers'], (id, answer) => { + $.each(data["answers"], (id, answer) => { const img = getImage(answer); el = $(`#inputtype_${id}`); - expect(img).toImageDiffEqual(el.find('canvas')[0]); + expect(img).toImageDiffEqual(el.find("canvas")[0]); }); }; - var stubRequest = data => { - spyOn($, 'postWithPrefix').and.callFake((url, callback) => callback(data)); + var stubRequest = (data) => { + spyOn($, "postWithPrefix").and.callFake((url, callback) => callback(data)); }; var getImage = (coords, c_width, c_height) => { let ctx, reg; const types = { - rectangle: coords => { + rectangle: (coords) => { reg = /^\(([0-9]+),([0-9]+)\)-\(([0-9]+),([0-9]+)\)$/; - const rects = coords.replace(/\s*/g, '').split(/;/); + const rects = coords.replace(/\s*/g, "").split(/;/); $.each(rects, (index, rect) => { const { abs } = Math; @@ -728,8 +780,8 @@ data-url='/problem/quiz/'> \ ctx.fill(); }, - regions: coords => { - const parseCoords = coords => { + regions: (coords) => { + const parseCoords = (coords) => { reg = JSON.parse(coords); if (typeof reg[0][0][0] === "undefined") { @@ -753,276 +805,295 @@ data-url='/problem/quiz/'> \ ctx.stroke(); ctx.fill(); }); - } + }, }; - const canvas = document.createElement('canvas'); + const canvas = document.createElement("canvas"); canvas.width = c_width || 100; canvas.height = c_height || 100; if (canvas.getContext) { - ctx = canvas.getContext('2d'); + ctx = canvas.getContext("2d"); } else { - console.log('Canvas is not supported.'); + console.log("Canvas is not supported."); } - ctx.fillStyle = 'rgba(255,255,255,.3)'; + ctx.fillStyle = "rgba(255,255,255,.3)"; ctx.strokeStyle = "#FF0000"; ctx.lineWidth = "2"; $.each(coords, (key, value) => { - if ((types[key] != null) && value) { return types[key](value); } + if (types[key] != null && value) { + return types[key](value); + } }); return canvas; }; - it('rectangle is drawn correctly', function() { + it("rectangle is drawn correctly", function () { assertAnswer(this.problem, { - 'answers': { - '12345': { - 'rectangle': '(10,10)-(30,30)', - 'regions': null - } - } + answers: { + 12345: { + rectangle: "(10,10)-(30,30)", + regions: null, + }, + }, }); }); - it('region is drawn correctly', function() { + it("region is drawn correctly", function () { assertAnswer(this.problem, { - 'answers': { - '12345': { - 'rectangle': null, - 'regions': '[[10,10],[30,30],[70,30],[20,30]]' - } - } + answers: { + 12345: { + rectangle: null, + regions: "[[10,10],[30,30],[70,30],[20,30]]", + }, + }, }); }); - it('mixed shapes are drawn correctly', function() { + it("mixed shapes are drawn correctly", function () { assertAnswer(this.problem, { - 'answers': {'12345': { - 'rectangle': '(10,10)-(30,30);(5,5)-(20,20)', - 'regions': `[ + answers: { + 12345: { + rectangle: "(10,10)-(30,30);(5,5)-(20,20)", + regions: `[ [[50,50],[40,40],[70,30],[50,70]], [[90,95],[95,95],[90,70],[70,70]] -]` - } - } +]`, + }, + }, }); }); - it('multiple image inputs draw answers on separate canvases', function() { + it("multiple image inputs draw answers on separate canvases", function () { const data = { - id: '67890', - width: '400', - height: '300' + id: "67890", + width: "400", + height: "300", }; this.problem.el.prepend(_.template(imageinput_html)(data)); assertAnswer(this.problem, { - 'answers': { - '12345': { - 'rectangle': null, - 'regions': '[[10,10],[30,30],[70,30],[20,30]]' + answers: { + 12345: { + rectangle: null, + regions: "[[10,10],[30,30],[70,30],[20,30]]", }, - '67890': { - 'rectangle': '(10,10)-(30,30)', - 'regions': null - } - } + 67890: { + rectangle: "(10,10)-(30,30)", + regions: null, + }, + }, }); }); - it('dictionary with answers doesn\'t contain answer for current id', function() { - spyOn(console, 'log'); - stubRequest({'answers':{}}); + it("dictionary with answers doesn't contain answer for current id", function () { + spyOn(console, "log"); + stubRequest({ answers: {} }); this.problem.show(); - el = $('#inputtype_12345'); - expect(el.find('canvas')).not.toExist(); - expect(console.log).toHaveBeenCalledWith('Answer is absent for image input with id=12345'); + el = $("#inputtype_12345"); + expect(el.find("canvas")).not.toExist(); + expect(console.log).toHaveBeenCalledWith("Answer is absent for image input with id=12345"); }); }); }); }); - describe('save', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); - this.problem.answers = 'foo=1&bar=2'; + describe("save", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); + this.problem.answers = "foo=1&bar=2"; }); - it('log the problem_save event', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("log the problem_save event", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - promise = - {always(callable) { return callable(); }}; + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); this.problem.save(); - expect(Logger.log).toHaveBeenCalledWith('problem_save', 'foo=1&bar=2'); + expect(Logger.log).toHaveBeenCalledWith("problem_save", "foo=1&bar=2"); }); - it('POST to save problem', function() { - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + it("POST to save problem", function () { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { let promise; - promise = - {always(callable) { return callable(); }}; + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); this.problem.save(); - expect($.postWithPrefix).toHaveBeenCalledWith('/problem/Problem1/problem_save', - 'foo=1&bar=2', jasmine.any(Function)); + expect($.postWithPrefix).toHaveBeenCalledWith( + "/problem/Problem1/problem_save", + "foo=1&bar=2", + jasmine.any(Function), + ); }); - it('tests that save does not enable the submit button or change the text when submit is originally disabled', function() { + it("tests that save does not enable the submit button or change the text when submit is originally disabled", function () { const self = this; const curr_html = this.problem.el.html(); - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { // enableButtons should have been called at this point and the submit button should be unaffected let promise; - expect(self.problem.submitButton).toHaveAttr('disabled'); - expect(self.problem.submitButtonLabel.text()).toBe('Submit'); - callback({success: 'correct', html: curr_html}); - promise = - {always(callable) { return callable(); }}; + expect(self.problem.submitButton).toHaveAttr("disabled"); + expect(self.problem.submitButtonLabel.text()).toBe("Submit"); + callback({ success: "correct", html: curr_html }); + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); // Expect submit to be disabled and labeled properly at the start - expect(this.problem.submitButton).toHaveAttr('disabled'); - expect(this.problem.submitButtonLabel.text()).toBe('Submit'); + expect(this.problem.submitButton).toHaveAttr("disabled"); + expect(this.problem.submitButtonLabel.text()).toBe("Submit"); this.problem.save(); // Submit button should have the same state after save has completed - expect(this.problem.submitButton).toHaveAttr('disabled'); - expect(this.problem.submitButtonLabel.text()).toBe('Submit'); + expect(this.problem.submitButton).toHaveAttr("disabled"); + expect(this.problem.submitButtonLabel.text()).toBe("Submit"); }); - it('tests that save does not disable the submit button or change the text when submit is originally enabled', function() { + it("tests that save does not disable the submit button or change the text when submit is originally enabled", function () { const self = this; const curr_html = this.problem.el.html(); - spyOn($, 'postWithPrefix').and.callFake(function(url, answers, callback) { + spyOn($, "postWithPrefix").and.callFake(function (url, answers, callback) { // enableButtons should have been called at this point, and the submit button should be disabled while submitting let promise; - expect(self.problem.submitButton).toHaveAttr('disabled'); - expect(self.problem.submitButtonLabel.text()).toBe('Submit'); - callback({success: 'correct', html: curr_html}); - promise = - {always(callable) { return callable(); }}; + expect(self.problem.submitButton).toHaveAttr("disabled"); + expect(self.problem.submitButtonLabel.text()).toBe("Submit"); + callback({ success: "correct", html: curr_html }); + promise = { + always(callable) { + return callable(); + }, + }; return promise; }); // Expect submit to be enabled and labeled properly at the start after adding an input - $('#input_example_1').val('test').trigger('input'); - expect(this.problem.submitButton).not.toHaveAttr('disabled'); - expect(this.problem.submitButtonLabel.text()).toBe('Submit'); + $("#input_example_1").val("test").trigger("input"); + expect(this.problem.submitButton).not.toHaveAttr("disabled"); + expect(this.problem.submitButtonLabel.text()).toBe("Submit"); this.problem.save(); // Submit button should have the same state after save has completed - expect(this.problem.submitButton).not.toHaveAttr('disabled'); - expect(this.problem.submitButtonLabel.text()).toBe('Submit'); + expect(this.problem.submitButton).not.toHaveAttr("disabled"); + expect(this.problem.submitButtonLabel.text()).toBe("Submit"); }); }); - describe('refreshMath', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); - $('#input_example_1').val('E=mc^2'); - this.problem.refreshMath({target: $('#input_example_1').get(0)}); + describe("refreshMath", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); + $("#input_example_1").val("E=mc^2"); + this.problem.refreshMath({ target: $("#input_example_1").get(0) }); }); - it('should queue the conversion and MathML element update', function() { - expect(MathJax.Hub.Queue).toHaveBeenCalledWith(['Text', this.stubbedJax, 'E=mc^2'], - [this.problem.updateMathML, this.stubbedJax, $('#input_example_1').get(0)]); + it("should queue the conversion and MathML element update", function () { + expect(MathJax.Hub.Queue).toHaveBeenCalledWith( + ["Text", this.stubbedJax, "E=mc^2"], + [this.problem.updateMathML, this.stubbedJax, $("#input_example_1").get(0)], + ); + }); }); -}); - describe('updateMathML', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); - this.stubbedJax.root.toMathML.and.returnValue(''); + describe("updateMathML", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); + this.stubbedJax.root.toMathML.and.returnValue(""); }); - describe('when there is no exception', function() { - beforeEach(function() { - this.problem.updateMathML(this.stubbedJax, $('#input_example_1').get(0)); + describe("when there is no exception", function () { + beforeEach(function () { + this.problem.updateMathML(this.stubbedJax, $("#input_example_1").get(0)); }); - it('convert jax to MathML', () => expect($('#input_example_1_dynamath')).toHaveValue('')); + it("convert jax to MathML", () => expect($("#input_example_1_dynamath")).toHaveValue("")); }); - describe('when there is an exception', function() { - beforeEach(function() { + describe("when there is an exception", function () { + beforeEach(function () { const error = new Error(); error.restart = true; this.stubbedJax.root.toMathML.and.throwError(error); - this.problem.updateMathML(this.stubbedJax, $('#input_example_1').get(0)); + this.problem.updateMathML(this.stubbedJax, $("#input_example_1").get(0)); }); - it('should queue up the exception', function() { + it("should queue up the exception", function () { expect(MathJax.Callback.After).toHaveBeenCalledWith([this.problem.refreshMath, this.stubbedJax], true); }); }); }); - describe('refreshAnswers', function() { - beforeEach(function() { - this.problem = new Problem($('.xblock-student_view')); + describe("refreshAnswers", function () { + beforeEach(function () { + this.problem = new Problem($(".xblock-student_view")); this.problem.el.html(`\