diff --git a/cms/static/coffee/spec/models/course_spec.js b/cms/static/coffee/spec/models/course_spec.js index b6dc658e5a..2bdb333f57 100644 --- a/cms/static/coffee/spec/models/course_spec.js +++ b/cms/static/coffee/spec/models/course_spec.js @@ -1,10 +1,20 @@ -define ["js/models/course"], (Course) -> - describe "Course", -> - describe "basic", -> - beforeEach -> - @model = new Course({ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +define(["js/models/course"], Course => + describe("Course", () => + describe("basic", function() { + beforeEach(function() { + return this.model = new Course({ name: "Greek Hero" - }) + }); + }); - it "should take a name argument", -> - expect(@model.get("name")).toEqual("Greek Hero") + return it("should take a name argument", function() { + return expect(this.model.get("name")).toEqual("Greek Hero"); + }); + }) + ) +); diff --git a/cms/static/coffee/spec/models/metadata_spec.js b/cms/static/coffee/spec/models/metadata_spec.js index ba3c4a2b65..dd5bbea0f3 100644 --- a/cms/static/coffee/spec/models/metadata_spec.js +++ b/cms/static/coffee/spec/models/metadata_spec.js @@ -1,59 +1,74 @@ -define ["js/models/metadata"], (Metadata) -> - describe "Metadata", -> - it "knows when the value has not been modified", -> - model = new Metadata( - {'value': 'original', 'explicitly_set': false}) - expect(model.isModified()).toBeFalsy() +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +define(["js/models/metadata"], Metadata => + describe("Metadata", function() { + it("knows when the value has not been modified", function() { + let model = new Metadata( + {'value': 'original', 'explicitly_set': false}); + expect(model.isModified()).toBeFalsy(); model = new Metadata( - {'value': 'original', 'explicitly_set': true}) - model.setValue('original') - expect(model.isModified()).toBeFalsy() + {'value': 'original', 'explicitly_set': true}); + model.setValue('original'); + return expect(model.isModified()).toBeFalsy(); + }); - it "knows when the value has been modified", -> - model = new Metadata( - {'value': 'original', 'explicitly_set': false}) - model.setValue('original') - expect(model.isModified()).toBeTruthy() + it("knows when the value has been modified", function() { + let model = new Metadata( + {'value': 'original', 'explicitly_set': false}); + model.setValue('original'); + expect(model.isModified()).toBeTruthy(); model = new Metadata( - {'value': 'original', 'explicitly_set': true}) - model.setValue('modified') - expect(model.isModified()).toBeTruthy() + {'value': 'original', 'explicitly_set': true}); + model.setValue('modified'); + return expect(model.isModified()).toBeTruthy(); + }); - it "tracks when values have been explicitly set", -> - model = new Metadata( - {'value': 'original', 'explicitly_set': false}) - expect(model.isExplicitlySet()).toBeFalsy() - model.setValue('original') - expect(model.isExplicitlySet()).toBeTruthy() + it("tracks when values have been explicitly set", function() { + const model = new Metadata( + {'value': 'original', 'explicitly_set': false}); + expect(model.isExplicitlySet()).toBeFalsy(); + model.setValue('original'); + return expect(model.isExplicitlySet()).toBeTruthy(); + }); - it "has both 'display value' and a 'value' methods", -> - model = new Metadata( - {'value': 'default', 'explicitly_set': false}) - expect(model.getValue()).toBeNull - expect(model.getDisplayValue()).toBe('default') - model.setValue('modified') - expect(model.getValue()).toBe('modified') - expect(model.getDisplayValue()).toBe('modified') + it("has both 'display value' and a 'value' methods", function() { + const model = new Metadata( + {'value': 'default', 'explicitly_set': false}); + expect(model.getValue()).toBeNull; + expect(model.getDisplayValue()).toBe('default'); + model.setValue('modified'); + expect(model.getValue()).toBe('modified'); + return expect(model.getDisplayValue()).toBe('modified'); + }); - it "has a clear method for reverting to the default", -> - model = new Metadata( - {'value': 'original', 'default_value' : 'default', 'explicitly_set': true}) - model.clear() - expect(model.getValue()).toBeNull - expect(model.getDisplayValue()).toBe('default') - expect(model.isExplicitlySet()).toBeFalsy() + it("has a clear method for reverting to the default", function() { + const model = new Metadata( + {'value': 'original', 'default_value' : 'default', 'explicitly_set': true}); + model.clear(); + expect(model.getValue()).toBeNull; + expect(model.getDisplayValue()).toBe('default'); + return expect(model.isExplicitlySet()).toBeFalsy(); + }); - it "has a getter for field name", -> - model = new Metadata({'field_name': 'foo'}) - expect(model.getFieldName()).toBe('foo') + it("has a getter for field name", function() { + const model = new Metadata({'field_name': 'foo'}); + return expect(model.getFieldName()).toBe('foo'); + }); - it "has a getter for options", -> - model = new Metadata({'options': ['foo', 'bar']}) - expect(model.getOptions()).toEqual(['foo', 'bar']) + it("has a getter for options", function() { + const model = new Metadata({'options': ['foo', 'bar']}); + return expect(model.getOptions()).toEqual(['foo', 'bar']); + }); - it "has a getter for type", -> - model = new Metadata({'type': 'Integer'}) - expect(model.getType()).toBe(Metadata.INTEGER_TYPE) + return it("has a getter for type", function() { + const model = new Metadata({'type': 'Integer'}); + return expect(model.getType()).toBe(Metadata.INTEGER_TYPE); + }); + }) +); diff --git a/cms/static/coffee/spec/models/section_spec.js b/cms/static/coffee/spec/models/section_spec.js index 8a954b50dc..011099773e 100644 --- a/cms/static/coffee/spec/models/section_spec.js +++ b/cms/static/coffee/spec/models/section_spec.js @@ -1,50 +1,67 @@ -define ["js/models/section", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers", "js/utils/module"], (Section, AjaxHelpers, ModuleUtils) -> - describe "Section", -> - describe "basic", -> - beforeEach -> - @model = new Section({ - id: 42 +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +define(["js/models/section", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers", "js/utils/module"], (Section, AjaxHelpers, ModuleUtils) => + describe("Section", function() { + describe("basic", function() { + beforeEach(function() { + return this.model = new Section({ + id: 42, name: "Life, the Universe, and Everything" - }) + }); + }); - it "should take an id argument", -> - expect(@model.get("id")).toEqual(42) + it("should take an id argument", function() { + return expect(this.model.get("id")).toEqual(42); + }); - it "should take a name argument", -> - expect(@model.get("name")).toEqual("Life, the Universe, and Everything") + it("should take a name argument", function() { + return expect(this.model.get("name")).toEqual("Life, the Universe, and Everything"); + }); - it "should have a URL set", -> - expect(@model.url()).toEqual(ModuleUtils.getUpdateUrl(42)) + it("should have a URL set", function() { + return expect(this.model.url()).toEqual(ModuleUtils.getUpdateUrl(42)); + }); - it "should serialize to JSON correctly", -> - expect(@model.toJSON()).toEqual({ + return it("should serialize to JSON correctly", function() { + return expect(this.model.toJSON()).toEqual({ metadata: { display_name: "Life, the Universe, and Everything" } - }) + }); + }); + }); - describe "XHR", -> - beforeEach -> - spyOn(Section.prototype, 'showNotification') - spyOn(Section.prototype, 'hideNotification') - @model = new Section({ - id: 42 + return describe("XHR", function() { + beforeEach(function() { + spyOn(Section.prototype, 'showNotification'); + spyOn(Section.prototype, 'hideNotification'); + return this.model = new Section({ + id: 42, name: "Life, the Universe, and Everything" - }) + }); + }); - it "show/hide a notification when it saves to the server", -> - server = AjaxHelpers.server([200, {"Content-Type": "application/json"}, "{}"]) + it("show/hide a notification when it saves to the server", function() { + const server = AjaxHelpers.server([200, {"Content-Type": "application/json"}, "{}"]); - @model.save() - expect(Section.prototype.showNotification).toHaveBeenCalled() - server.respond() - expect(Section.prototype.hideNotification).toHaveBeenCalled() + this.model.save(); + expect(Section.prototype.showNotification).toHaveBeenCalled(); + server.respond(); + return expect(Section.prototype.hideNotification).toHaveBeenCalled(); + }); - it "don't hide notification when saving fails", -> - # this is handled by the global AJAX error handler - server = AjaxHelpers.server([500, {"Content-Type": "application/json"}, "{}"]) + return it("don't hide notification when saving fails", function() { + // this is handled by the global AJAX error handler + const server = AjaxHelpers.server([500, {"Content-Type": "application/json"}, "{}"]); - @model.save() - server.respond() - expect(Section.prototype.hideNotification).not.toHaveBeenCalled() + this.model.save(); + server.respond(); + return expect(Section.prototype.hideNotification).not.toHaveBeenCalled(); + }); + }); + }) +); diff --git a/cms/static/coffee/spec/models/settings_course_grader_spec.js b/cms/static/coffee/spec/models/settings_course_grader_spec.js index 23cf22d371..1d0ba32d92 100644 --- a/cms/static/coffee/spec/models/settings_course_grader_spec.js +++ b/cms/static/coffee/spec/models/settings_course_grader_spec.js @@ -1,39 +1,52 @@ -define ["js/models/settings/course_grader"], (CourseGrader) -> - describe "CourseGraderModel", -> - describe "parseWeight", -> - it "converts a float to an integer", -> - model = new CourseGrader({weight: 7.0001, min_count: 3.67, drop_count: 1.88}, {parse:true}) - expect(model.get('weight')).toBe(7) - expect(model.get('min_count')).toBe(4) - expect(model.get('drop_count')).toBe(2) +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +define(["js/models/settings/course_grader"], CourseGrader => + describe("CourseGraderModel", () => + describe("parseWeight", function() { + it("converts a float to an integer", function() { + const model = new CourseGrader({weight: 7.0001, min_count: 3.67, drop_count: 1.88}, {parse:true}); + expect(model.get('weight')).toBe(7); + expect(model.get('min_count')).toBe(4); + return expect(model.get('drop_count')).toBe(2); + }); - it "converts float value of weight to an integer with rounding", -> - model = new CourseGrader({weight: 28.999999999999996}, {parse:true}) - expect(model.get('weight')).toBe(29) + it("converts float value of weight to an integer with rounding", function() { + const model = new CourseGrader({weight: 28.999999999999996}, {parse:true}); + return expect(model.get('weight')).toBe(29); + }); - it "converts a string to an integer", -> - model = new CourseGrader({weight: '7.0001', min_count: '3.67', drop_count: '1.88'}, {parse:true}) - expect(model.get('weight')).toBe(7) - expect(model.get('min_count')).toBe(4) - expect(model.get('drop_count')).toBe(2) + it("converts a string to an integer", function() { + const model = new CourseGrader({weight: '7.0001', min_count: '3.67', drop_count: '1.88'}, {parse:true}); + expect(model.get('weight')).toBe(7); + expect(model.get('min_count')).toBe(4); + return expect(model.get('drop_count')).toBe(2); + }); - it "does a no-op for integers", -> - model = new CourseGrader({weight: 7, min_count: 3, drop_count: 1}, {parse:true}) - expect(model.get('weight')).toBe(7) - expect(model.get('min_count')).toBe(3) - expect(model.get('drop_count')).toBe(1) + it("does a no-op for integers", function() { + const model = new CourseGrader({weight: 7, min_count: 3, drop_count: 1}, {parse:true}); + expect(model.get('weight')).toBe(7); + expect(model.get('min_count')).toBe(3); + return expect(model.get('drop_count')).toBe(1); + }); - it "gives validation error if min_count is less than 1 or drop_count is NaN", -> - model = new CourseGrader() - errors = model.validate({min_count: 0, drop_count: ''}, {validate:true}) - expect(errors.min_count).toBe('Please enter an integer greater than 0.') - expect(errors.drop_count).toBe('Please enter non-negative integer.') - # don't allow negative integers - errors = model.validate({min_count: -12, drop_count: -1}, {validate:true}) - expect(errors.min_count).toBe('Please enter an integer greater than 0.') - expect(errors.drop_count).toBe('Please enter non-negative integer.') - # don't allow floats - errors = model.validate({min_count: 12.2, drop_count: 1.5}, {validate:true}) - expect(errors.min_count).toBe('Please enter an integer greater than 0.') - expect(errors.drop_count).toBe('Please enter non-negative integer.') + return it("gives validation error if min_count is less than 1 or drop_count is NaN", function() { + const model = new CourseGrader(); + let errors = model.validate({min_count: 0, drop_count: ''}, {validate:true}); + expect(errors.min_count).toBe('Please enter an integer greater than 0.'); + expect(errors.drop_count).toBe('Please enter non-negative integer.'); + // don't allow negative integers + errors = model.validate({min_count: -12, drop_count: -1}, {validate:true}); + expect(errors.min_count).toBe('Please enter an integer greater than 0.'); + expect(errors.drop_count).toBe('Please enter non-negative integer.'); + // don't allow floats + errors = model.validate({min_count: 12.2, drop_count: 1.5}, {validate:true}); + expect(errors.min_count).toBe('Please enter an integer greater than 0.'); + return expect(errors.drop_count).toBe('Please enter non-negative integer.'); + }); + }) + ) +); diff --git a/cms/static/coffee/spec/models/settings_grading_spec.js b/cms/static/coffee/spec/models/settings_grading_spec.js index 4092f4f161..6238024fef 100644 --- a/cms/static/coffee/spec/models/settings_grading_spec.js +++ b/cms/static/coffee/spec/models/settings_grading_spec.js @@ -1,36 +1,52 @@ -define ["underscore", "js/models/settings/course_grading_policy"], (_, CourseGradingPolicy) -> - describe "CourseGradingPolicy", -> - beforeEach -> - @model = new CourseGradingPolicy() +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +define(["underscore", "js/models/settings/course_grading_policy"], (_, CourseGradingPolicy) => + describe("CourseGradingPolicy", function() { + beforeEach(function() { + return this.model = new CourseGradingPolicy(); + }); - describe "parse", -> - it "sets a null grace period to 00:00", -> - attrs = @model.parse(grace_period: null) - expect(attrs.grace_period).toEqual( + describe("parse", () => + it("sets a null grace period to 00:00", function() { + const attrs = this.model.parse({grace_period: null}); + return expect(attrs.grace_period).toEqual({ hours: 0, minutes: 0 - ) + }); + }) + ); - describe "parseGracePeriod", -> - it "parses a time in HH:MM format", -> - time = @model.parseGracePeriod("07:19") - expect(time).toEqual( + describe("parseGracePeriod", function() { + it("parses a time in HH:MM format", function() { + const time = this.model.parseGracePeriod("07:19"); + return expect(time).toEqual({ hours: 7, minutes: 19 - ) + }); + }); - it "returns null on an incorrectly formatted string", -> - expect(@model.parseGracePeriod("asdf")).toBe(null) - expect(@model.parseGracePeriod("7:19")).toBe(null) - expect(@model.parseGracePeriod("1000:00")).toBe(null) + return it("returns null on an incorrectly formatted string", function() { + expect(this.model.parseGracePeriod("asdf")).toBe(null); + expect(this.model.parseGracePeriod("7:19")).toBe(null); + return expect(this.model.parseGracePeriod("1000:00")).toBe(null); + }); + }); - describe "validate", -> - it "enforces that the passing grade is <= the minimum grade to receive credit if credit is enabled", -> - @model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: true}) - @model.set('grade_cutoffs', [0.9], validate: true) - expect(_.keys(@model.validationError)).toContain('minimum_grade_credit') + return describe("validate", function() { + it("enforces that the passing grade is <= the minimum grade to receive credit if credit is enabled", function() { + this.model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: true}); + this.model.set('grade_cutoffs', [0.9], {validate: true}); + return expect(_.keys(this.model.validationError)).toContain('minimum_grade_credit'); + }); - it "does not enforce the passing grade limit in non-credit courses", -> - @model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: false}) - @model.set({grade_cutoffs: [0.9]}, validate: true) - expect(@model.validationError).toBe(null) + return it("does not enforce the passing grade limit in non-credit courses", function() { + this.model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: false}); + this.model.set({grade_cutoffs: [0.9]}, {validate: true}); + return expect(this.model.validationError).toBe(null); + }); + }); + }) +); diff --git a/cms/static/coffee/spec/models/textbook_spec.js b/cms/static/coffee/spec/models/textbook_spec.js index dc10df8a47..75ac6f875a 100644 --- a/cms/static/coffee/spec/models/textbook_spec.js +++ b/cms/static/coffee/spec/models/textbook_spec.js @@ -1,78 +1,98 @@ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS203: Remove `|| {}` from converted for-own loops + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ -define ["backbone", "js/models/textbook", "js/collections/textbook", "js/models/chapter", "js/collections/chapter", "cms/js/main"], -(Backbone, Textbook, TextbookSet, Chapter, ChapterSet, main) -> +define(["backbone", "js/models/textbook", "js/collections/textbook", "js/models/chapter", "js/collections/chapter", "cms/js/main"], +function(Backbone, Textbook, TextbookSet, Chapter, ChapterSet, main) { - describe "Textbook model", -> - beforeEach -> - main() - @model = new Textbook() - CMS.URL.TEXTBOOKS = "/textbooks" + describe("Textbook model", function() { + beforeEach(function() { + main(); + this.model = new Textbook(); + return CMS.URL.TEXTBOOKS = "/textbooks"; + }); - afterEach -> - delete CMS.URL.TEXTBOOKS + afterEach(() => delete CMS.URL.TEXTBOOKS); - describe "Basic", -> - it "should have an empty name by default", -> - expect(@model.get("name")).toEqual("") + describe("Basic", function() { + it("should have an empty name by default", function() { + return expect(this.model.get("name")).toEqual(""); + }); - it "should not show chapters by default", -> - expect(@model.get("showChapters")).toBeFalsy() + it("should not show chapters by default", function() { + return expect(this.model.get("showChapters")).toBeFalsy(); + }); - it "should have a ChapterSet with one chapter by default", -> - chapters = @model.get("chapters") - expect(chapters).toBeInstanceOf(ChapterSet) - expect(chapters.length).toEqual(1) - expect(chapters.at(0).isEmpty()).toBeTruthy() + it("should have a ChapterSet with one chapter by default", function() { + const chapters = this.model.get("chapters"); + expect(chapters).toBeInstanceOf(ChapterSet); + expect(chapters.length).toEqual(1); + return expect(chapters.at(0).isEmpty()).toBeTruthy(); + }); - it "should be empty by default", -> - expect(@model.isEmpty()).toBeTruthy() + it("should be empty by default", function() { + return expect(this.model.isEmpty()).toBeTruthy(); + }); - it "should have a URL root", -> - urlRoot = _.result(@model, 'urlRoot') - expect(urlRoot).toBeTruthy() + it("should have a URL root", function() { + const urlRoot = _.result(this.model, 'urlRoot'); + return expect(urlRoot).toBeTruthy(); + }); - it "should be able to reset itself", -> - @model.set("name", "foobar") - @model.reset() - expect(@model.get("name")).toEqual("") + it("should be able to reset itself", function() { + this.model.set("name", "foobar"); + this.model.reset(); + return expect(this.model.get("name")).toEqual(""); + }); - it "should not be dirty by default", -> - expect(@model.isDirty()).toBeFalsy() + it("should not be dirty by default", function() { + return expect(this.model.isDirty()).toBeFalsy(); + }); - it "should be dirty after it's been changed", -> - @model.set("name", "foobar") - expect(@model.isDirty()).toBeTruthy() + it("should be dirty after it's been changed", function() { + this.model.set("name", "foobar"); + return expect(this.model.isDirty()).toBeTruthy(); + }); - it "should not be dirty after calling setOriginalAttributes", -> - @model.set("name", "foobar") - @model.setOriginalAttributes() - expect(@model.isDirty()).toBeFalsy() + return it("should not be dirty after calling setOriginalAttributes", function() { + this.model.set("name", "foobar"); + this.model.setOriginalAttributes(); + return expect(this.model.isDirty()).toBeFalsy(); + }); + }); - describe "Input/Output", -> - deepAttributes = (obj) -> - if obj instanceof Backbone.Model - deepAttributes(obj.attributes) - else if obj instanceof Backbone.Collection - obj.map(deepAttributes); - else if _.isArray(obj) - _.map(obj, deepAttributes); - else if _.isObject(obj) - attributes = {}; - for own prop, val of obj - attributes[prop] = deepAttributes(val) - attributes - else - obj + describe("Input/Output", function() { + var deepAttributes = function(obj) { + if (obj instanceof Backbone.Model) { + return deepAttributes(obj.attributes); + } else if (obj instanceof Backbone.Collection) { + return obj.map(deepAttributes); + } else if (_.isArray(obj)) { + return _.map(obj, deepAttributes); + } else if (_.isObject(obj)) { + const attributes = {}; + for (let prop of Object.keys(obj || {})) { + const val = obj[prop]; + attributes[prop] = deepAttributes(val); + } + return attributes; + } else { + return obj; + } + }; - it "should match server model to client model", -> - serverModelSpec = { + return it("should match server model to client model", function() { + const serverModelSpec = { "tab_title": "My Textbook", "chapters": [ {"title": "Chapter 1", "url": "/ch1.pdf"}, {"title": "Chapter 2", "url": "/ch2.pdf"}, ] - } - clientModelSpec = { + }; + const clientModelSpec = { "name": "My Textbook", "showChapters": false, "editing": false, @@ -86,113 +106,142 @@ define ["backbone", "js/models/textbook", "js/collections/textbook", "js/models/ "order": 2 } ] - } + }; - model = new Textbook(serverModelSpec, {parse: true}) - expect(deepAttributes(model)).toEqual(clientModelSpec) - expect(model.toJSON()).toEqual(serverModelSpec) + const model = new Textbook(serverModelSpec, {parse: true}); + expect(deepAttributes(model)).toEqual(clientModelSpec); + return expect(model.toJSON()).toEqual(serverModelSpec); + }); + }); - describe "Validation", -> - it "requires a name", -> - model = new Textbook({name: ""}) - expect(model.isValid()).toBeFalsy() + return describe("Validation", function() { + it("requires a name", function() { + const model = new Textbook({name: ""}); + return expect(model.isValid()).toBeFalsy(); + }); - it "requires at least one chapter", -> - model = new Textbook({name: "foo"}) - model.get("chapters").reset() - expect(model.isValid()).toBeFalsy() + it("requires at least one chapter", function() { + const model = new Textbook({name: "foo"}); + model.get("chapters").reset(); + return expect(model.isValid()).toBeFalsy(); + }); - it "requires a valid chapter", -> - chapter = new Chapter() - chapter.isValid = -> false - model = new Textbook({name: "foo"}) - model.get("chapters").reset([chapter]) - expect(model.isValid()).toBeFalsy() + it("requires a valid chapter", function() { + const chapter = new Chapter(); + chapter.isValid = () => false; + const model = new Textbook({name: "foo"}); + model.get("chapters").reset([chapter]); + return expect(model.isValid()).toBeFalsy(); + }); - it "requires all chapters to be valid", -> - chapter1 = new Chapter() - chapter1.isValid = -> true - chapter2 = new Chapter() - chapter2.isValid = -> false - model = new Textbook({name: "foo"}) - model.get("chapters").reset([chapter1, chapter2]) - expect(model.isValid()).toBeFalsy() + it("requires all chapters to be valid", function() { + const chapter1 = new Chapter(); + chapter1.isValid = () => true; + const chapter2 = new Chapter(); + chapter2.isValid = () => false; + const model = new Textbook({name: "foo"}); + model.get("chapters").reset([chapter1, chapter2]); + return expect(model.isValid()).toBeFalsy(); + }); - it "can pass validation", -> - chapter = new Chapter() - chapter.isValid = -> true - model = new Textbook({name: "foo"}) - model.get("chapters").reset([chapter]) - expect(model.isValid()).toBeTruthy() + return it("can pass validation", function() { + const chapter = new Chapter(); + chapter.isValid = () => true; + const model = new Textbook({name: "foo"}); + model.get("chapters").reset([chapter]); + return expect(model.isValid()).toBeTruthy(); + }); + }); + }); - describe "Textbook collection", -> - beforeEach -> - CMS.URL.TEXTBOOKS = "/textbooks" - @collection = new TextbookSet() + describe("Textbook collection", function() { + beforeEach(function() { + CMS.URL.TEXTBOOKS = "/textbooks"; + return this.collection = new TextbookSet(); + }); - afterEach -> - delete CMS.URL.TEXTBOOKS + afterEach(() => delete CMS.URL.TEXTBOOKS); - it "should have a url set", -> - url = _.result(@collection, 'url') - expect(url).toEqual("/textbooks") + return it("should have a url set", function() { + const url = _.result(this.collection, 'url'); + return expect(url).toEqual("/textbooks"); + }); + }); - describe "Chapter model", -> - beforeEach -> - @model = new Chapter() + describe("Chapter model", function() { + beforeEach(function() { + return this.model = new Chapter(); + }); - describe "Basic", -> - it "should have a name by default", -> - expect(@model.get("name")).toEqual("") + describe("Basic", function() { + it("should have a name by default", function() { + return expect(this.model.get("name")).toEqual(""); + }); - it "should have an asset_path by default", -> - expect(@model.get("asset_path")).toEqual("") + it("should have an asset_path by default", function() { + return expect(this.model.get("asset_path")).toEqual(""); + }); - it "should have an order by default", -> - expect(@model.get("order")).toEqual(1) + it("should have an order by default", function() { + return expect(this.model.get("order")).toEqual(1); + }); - it "should be empty by default", -> - expect(@model.isEmpty()).toBeTruthy() + return it("should be empty by default", function() { + return expect(this.model.isEmpty()).toBeTruthy(); + }); + }); - describe "Validation", -> - it "requires a name", -> - model = new Chapter({name: "", asset_path: "a.pdf"}) - expect(model.isValid()).toBeFalsy() + return describe("Validation", function() { + it("requires a name", function() { + const model = new Chapter({name: "", asset_path: "a.pdf"}); + return expect(model.isValid()).toBeFalsy(); + }); - it "requires an asset_path", -> - model = new Chapter({name: "a", asset_path: ""}) - expect(model.isValid()).toBeFalsy() + it("requires an asset_path", function() { + const model = new Chapter({name: "a", asset_path: ""}); + return expect(model.isValid()).toBeFalsy(); + }); - it "can pass validation", -> - model = new Chapter({name: "a", asset_path: "a.pdf"}) - expect(model.isValid()).toBeTruthy() + return it("can pass validation", function() { + const model = new Chapter({name: "a", asset_path: "a.pdf"}); + return expect(model.isValid()).toBeTruthy(); + }); + }); + }); - describe "Chapter collection", -> - beforeEach -> - @collection = new ChapterSet() + return describe("Chapter collection", function() { + beforeEach(function() { + return this.collection = new ChapterSet(); + }); - it "is empty by default", -> - expect(@collection.isEmpty()).toBeTruthy() + it("is empty by default", function() { + return expect(this.collection.isEmpty()).toBeTruthy(); + }); - it "is empty if all chapters are empty", -> - @collection.add([{}, {}, {}]) - expect(@collection.isEmpty()).toBeTruthy() + it("is empty if all chapters are empty", function() { + this.collection.add([{}, {}, {}]); + return expect(this.collection.isEmpty()).toBeTruthy(); + }); - it "is not empty if a chapter is not empty", -> - @collection.add([{}, {name: "full"}, {}]) - expect(@collection.isEmpty()).toBeFalsy() + it("is not empty if a chapter is not empty", function() { + this.collection.add([{}, {name: "full"}, {}]); + return expect(this.collection.isEmpty()).toBeFalsy(); + }); - it "should have a nextOrder function", -> - expect(@collection.nextOrder()).toEqual(1) - @collection.add([{}]) - expect(@collection.nextOrder()).toEqual(2) - @collection.add([{}]) - expect(@collection.nextOrder()).toEqual(3) - # verify that it doesn't just return an incrementing value each time - expect(@collection.nextOrder()).toEqual(3) - # try going back one - @collection.remove(@collection.last()) - expect(@collection.nextOrder()).toEqual(2) + return it("should have a nextOrder function", function() { + expect(this.collection.nextOrder()).toEqual(1); + this.collection.add([{}]); + expect(this.collection.nextOrder()).toEqual(2); + this.collection.add([{}]); + expect(this.collection.nextOrder()).toEqual(3); + // verify that it doesn't just return an incrementing value each time + expect(this.collection.nextOrder()).toEqual(3); + // try going back one + this.collection.remove(this.collection.last()); + return expect(this.collection.nextOrder()).toEqual(2); + }); + }); +}); diff --git a/cms/static/coffee/spec/models/upload_spec.js b/cms/static/coffee/spec/models/upload_spec.js index 17cd887b36..04900f7d7f 100644 --- a/cms/static/coffee/spec/models/upload_spec.js +++ b/cms/static/coffee/spec/models/upload_spec.js @@ -1,71 +1,93 @@ -define ["js/models/uploads"], (FileUpload) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +define(["js/models/uploads"], FileUpload => - describe "FileUpload", -> - beforeEach -> - @model = new FileUpload() + describe("FileUpload", function() { + beforeEach(function() { + return this.model = new FileUpload(); + }); - it "is unfinished by default", -> - expect(@model.get("finished")).toBeFalsy() + it("is unfinished by default", function() { + return expect(this.model.get("finished")).toBeFalsy(); + }); - it "is not uploading by default", -> - expect(@model.get("uploading")).toBeFalsy() + it("is not uploading by default", function() { + return expect(this.model.get("uploading")).toBeFalsy(); + }); - it "is valid by default", -> - expect(@model.isValid()).toBeTruthy() + it("is valid by default", function() { + return expect(this.model.isValid()).toBeTruthy(); + }); - it "is valid for text files by default", -> - file = {"type": "text/plain", "name": "filename.txt"} - @model.set("selectedFile", file); - expect(@model.isValid()).toBeTruthy() + it("is valid for text files by default", function() { + const file = {"type": "text/plain", "name": "filename.txt"}; + this.model.set("selectedFile", file); + return expect(this.model.isValid()).toBeTruthy(); + }); - it "is valid for PNG files by default", -> - file = {"type": "image/png", "name": "filename.png"} - @model.set("selectedFile", file); - expect(@model.isValid()).toBeTruthy() + it("is valid for PNG files by default", function() { + const file = {"type": "image/png", "name": "filename.png"}; + this.model.set("selectedFile", file); + return expect(this.model.isValid()).toBeTruthy(); + }); - it "can accept a file type when explicitly set", -> - file = {"type": "image/png", "name": "filename.png"} - @model.set("mimeTypes": ["image/png"]) - @model.set("selectedFile", file) - expect(@model.isValid()).toBeTruthy() + it("can accept a file type when explicitly set", function() { + const file = {"type": "image/png", "name": "filename.png"}; + this.model.set({"mimeTypes": ["image/png"]}); + this.model.set("selectedFile", file); + return expect(this.model.isValid()).toBeTruthy(); + }); - it "can accept a file format when explicitly set", -> - file = {"type": "", "name": "filename.png"} - @model.set("fileFormats": ["png"]) - @model.set("selectedFile", file) - expect(@model.isValid()).toBeTruthy() + it("can accept a file format when explicitly set", function() { + const file = {"type": "", "name": "filename.png"}; + this.model.set({"fileFormats": ["png"]}); + this.model.set("selectedFile", file); + return expect(this.model.isValid()).toBeTruthy(); + }); - it "can accept multiple file types", -> - file = {"type": "image/gif", "name": "filename.gif"} - @model.set("mimeTypes": ["image/png", "image/jpeg", "image/gif"]) - @model.set("selectedFile", file) - expect(@model.isValid()).toBeTruthy() + it("can accept multiple file types", function() { + const file = {"type": "image/gif", "name": "filename.gif"}; + this.model.set({"mimeTypes": ["image/png", "image/jpeg", "image/gif"]}); + this.model.set("selectedFile", file); + return expect(this.model.isValid()).toBeTruthy(); + }); - it "can accept multiple file formats", -> - file = {"type": "image/gif", "name": "filename.gif"} - @model.set("fileFormats": ["png", "jpeg", "gif"]) - @model.set("selectedFile", file) - expect(@model.isValid()).toBeTruthy() + it("can accept multiple file formats", function() { + const file = {"type": "image/gif", "name": "filename.gif"}; + this.model.set({"fileFormats": ["png", "jpeg", "gif"]}); + this.model.set("selectedFile", file); + return expect(this.model.isValid()).toBeTruthy(); + }); - describe "fileTypes", -> - it "returns a list of the uploader's file types", -> - @model.set('mimeTypes', ['image/png', 'application/json']) - @model.set('fileFormats', ['gif', 'srt']) - expect(@model.fileTypes()).toEqual(['PNG', 'JSON', 'GIF', 'SRT']) + describe("fileTypes", () => + it("returns a list of the uploader's file types", function() { + this.model.set('mimeTypes', ['image/png', 'application/json']); + this.model.set('fileFormats', ['gif', 'srt']); + return expect(this.model.fileTypes()).toEqual(['PNG', 'JSON', 'GIF', 'SRT']); + }) + ); - describe "formatValidTypes", -> - it "returns a map of formatted file types and extensions", -> - @model.set('mimeTypes', ['image/png', 'image/jpeg', 'application/json']) - formatted = @model.formatValidTypes() - expect(formatted).toEqual( + return describe("formatValidTypes", function() { + it("returns a map of formatted file types and extensions", function() { + this.model.set('mimeTypes', ['image/png', 'image/jpeg', 'application/json']); + const formatted = this.model.formatValidTypes(); + return expect(formatted).toEqual({ fileTypes: 'PNG, JPEG or JSON', fileExtensions: '.png, .jpeg or .json' - ) + }); + }); - it "does not format with only one mime type", -> - @model.set('mimeTypes', ['application/pdf']) - formatted = @model.formatValidTypes() - expect(formatted).toEqual( + return it("does not format with only one mime type", function() { + this.model.set('mimeTypes', ['application/pdf']); + const formatted = this.model.formatValidTypes(); + return expect(formatted).toEqual({ fileTypes: 'PDF', fileExtensions: '.pdf' - ) + }); + }); + }); + }) +); diff --git a/cms/static/coffee/spec/views/assets_spec.js b/cms/static/coffee/spec/views/assets_spec.js index e94d166a52..44a2a9d758 100644 --- a/cms/static/coffee/spec/views/assets_spec.js +++ b/cms/static/coffee/spec/views/assets_spec.js @@ -1,221 +1,252 @@ -define ["jquery", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers", "squire"], -($, AjaxHelpers, Squire) -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +define(["jquery", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers", "squire"], +function($, AjaxHelpers, Squire) { - assetLibraryTpl = readFixtures('asset-library.underscore') - assetTpl = readFixtures('asset.underscore') + const assetLibraryTpl = readFixtures('asset-library.underscore'); + const assetTpl = readFixtures('asset.underscore'); - describe "Asset view", -> - beforeEach (done) -> - setFixtures($(" + console.log(two * 2); + - But in this there should be -
- Great ideas require offsetting. +But in this there should be +
+Great ideas require offsetting. - bad tests require drivel -
+bad tests require drivel +
- [code] - Code should be nicely monospaced. - [/code] - """) - expect(data).toXMLEqual(""" - -

Not a header

-

A header

-

Multiple choice w/ parentheticals

- - - option (with parens) - xd option (x) - parentheses inside - no space b4 close paren - - -

Choice checks

- - - option1 [x] - correct - redundant - distractor - no space - - -

Option with multiple correct ones

- - - -

Option with embedded parens

- - - -

What happens w/ empty correct options?

- - - +[code] +Code should be nicely monospaced. +[/code]\ +`); + return expect(data).toXMLEqual(`\ + +

Not a header

+

A header

+

Multiple choice w/ parentheticals

+ + + option (with parens) + xd option (x) + parentheses inside + no space b4 close paren + + +

Choice checks

+ + + option1 [x] + correct + redundant + distractor + no space + + +

Option with multiple correct ones

+ + + +

Option with embedded parens

+ + + +

What happens w/ empty correct options?

+ + + + +
+

Explanation

+

see

+
+
+

[explanation]

+

orphaned start

+

No p tags in the below

+ +

But in this there should be

+
+

Great ideas require offsetting.

+

bad tests require drivel

+
+
+    Code should be nicely monospaced.
+
+  
+
`); + }); + + it('can separate responsetypes based on ---', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +Multiple choice problems allow learners to select only one option. Learners can see all the options along with the problem text. + +>>Which of the following countries has the largest population?<< +( ) Brazil {{ timely feedback -- explain why an almost correct answer is wrong }} +( ) Germany +(x) Indonesia +( ) Russia + +[explanation] +According to September 2014 estimates: +The population of Indonesia is approximately 250 million. +The population of Brazil is approximately 200 million. +The population of Russia is approximately 146 million. +The population of Germany is approximately 81 million. +[explanation] + +--- + +Checkbox problems allow learners to select multiple options. Learners can see all the options along with the problem text. + +>>The following languages are in the Indo-European family:<< +[x] Urdu +[ ] Finnish +[x] Marathi +[x] French +[ ] Hungarian + +Note: Make sure you select all of the correct options—there may be more than one! + +[explanation] +Urdu, Marathi, and French are all Indo-European languages, while Finnish and Hungarian are in the Uralic family. +[explanation] +\ +`); + return expect(data).toXMLEqual(`\ + + +

Multiple choice problems allow learners to select only one option. Learners can see all the options along with the problem text.

+ + + Brazil timely feedback -- explain why an almost correct answer is wrong + + Germany + Indonesia + Russia + + +
+

Explanation

+

According to September 2014 estimates:

+

The population of Indonesia is approximately 250 million.

+

The population of Brazil is approximately 200 million.

+

The population of Russia is approximately 146 million.

+

The population of Germany is approximately 81 million.

+
+
+
+ + +

Checkbox problems allow learners to select multiple options. Learners can see all the options along with the problem text.

+ + + Urdu + Finnish + Marathi + French + Hungarian + +

Note: Make sure you select all of the correct options—there may be more than one!

-

Explanation

-

see

+

Explanation

+

Urdu, Marathi, and French are all Indo-European languages, while Finnish and Hungarian are in the Uralic family.

-

[explanation]

-

orphaned start

-

No p tags in the below

- -

But in this there should be

-
-

Great ideas require offsetting.

-

bad tests require drivel

-
-
-          Code should be nicely monospaced.
-      
-        
-
""") + it('can separate other things based on ---', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +Multiple choice problems allow learners to select only one option. Learners can see all the options along with the problem text. - it 'can separate responsetypes based on ---', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - Multiple choice problems allow learners to select only one option. Learners can see all the options along with the problem text. +--- - >>Which of the following countries has the largest population?<< - ( ) Brazil {{ timely feedback -- explain why an almost correct answer is wrong }} - ( ) Germany - (x) Indonesia - ( ) Russia +>>Which of the following countries has the largest population?<< +( ) Brazil {{ timely feedback -- explain why an almost correct answer is wrong }} +( ) Germany +(x) Indonesia +( ) Russia - [explanation] - According to September 2014 estimates: - The population of Indonesia is approximately 250 million. - The population of Brazil is approximately 200 million. - The population of Russia is approximately 146 million. - The population of Germany is approximately 81 million. - [explanation] +[explanation] +According to September 2014 estimates: +The population of Indonesia is approximately 250 million. +The population of Brazil is approximately 200 million. +The population of Russia is approximately 146 million. +The population of Germany is approximately 81 million. +[explanation]\ +`); + return expect(data).toXMLEqual(`\ + +

Multiple choice problems allow learners to select only one option. Learners can see all the options along with the problem text.

+ + + + + Brazil timely feedback -- explain why an almost correct answer is wrong + + Germany + Indonesia + Russia + + +
+

Explanation

+

According to September 2014 estimates:

+

The population of Indonesia is approximately 250 million.

+

The population of Brazil is approximately 200 million.

+

The population of Russia is approximately 146 million.

+

The population of Germany is approximately 81 million.

+
+
+
+
\ +`); + }); + + it('can do separation if spaces are present around ---', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>The following languages are in the Indo-European family:||There are three correct choices.<< +[x] Urdu +[ ] Finnish +[x] Marathi +[x] French +[ ] Hungarian --- - Checkbox problems allow learners to select multiple options. Learners can see all the options along with the problem text. +>>Which of the following countries has the largest population?||You have only choice.<< +( ) Brazil {{ timely feedback -- explain why an almost correct answer is wrong }} +( ) Germany +(x) Indonesia +( ) Russia\ +`); + return expect(data).toXMLEqual(`\ + + + + There are three correct choices. + + Urdu + Finnish + Marathi + French + Hungarian + + - >>The following languages are in the Indo-European family:<< - [x] Urdu - [ ] Finnish - [x] Marathi - [x] French - [ ] Hungarian + + + You have only choice. + + Brazil + timely feedback -- explain why an almost correct answer is wrong + + Germany + Indonesia + Russia + + +\ +`); + }); - Note: Make sure you select all of the correct options—there may be more than one! + it('can extract question description', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>The following languages are in the Indo-European family:||Choose wisely.<< +[x] Urdu +[ ] Finnish +[x] Marathi +[x] French +[ ] Hungarian\ +`); + return expect(data).toXMLEqual(`\ + + + + Choose wisely. + + Urdu + Finnish + Marathi + French + Hungarian + + +\ +`); + }); - [explanation] - Urdu, Marathi, and French are all Indo-European languages, while Finnish and Hungarian are in the Uralic family. - [explanation] + it('can handle question and description spanned across multiple lines', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>The following languages +are in the +Indo-European family: +|| +first second +third +<< +[x] Urdu +[ ] Finnish +[x] Marathi\ +`); + return expect(data).toXMLEqual(`\ + + + + first second third + + Urdu + Finnish + Marathi + + +\ +`); + }); - """) - expect(data).toXMLEqual(""" - - -

Multiple choice problems allow learners to select only one option. Learners can see all the options along with the problem text.

- - - Brazil timely feedback -- explain why an almost correct answer is wrong - - Germany - Indonesia - Russia - - -
-

Explanation

-

According to September 2014 estimates:

-

The population of Indonesia is approximately 250 million.

-

The population of Brazil is approximately 200 million.

-

The population of Russia is approximately 146 million.

-

The population of Germany is approximately 81 million.

-
-
-
- - -

Checkbox problems allow learners to select multiple options. Learners can see all the options along with the problem text.

- - - Urdu - Finnish - Marathi - French - Hungarian - -

Note: Make sure you select all of the correct options—there may be more than one!

- -
-

Explanation

-

Urdu, Marathi, and French are all Indo-European languages, while Finnish and Hungarian are in the Uralic family.

-
-
-
-
- """) - - it 'can separate other things based on ---', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - Multiple choice problems allow learners to select only one option. Learners can see all the options along with the problem text. - - --- - - >>Which of the following countries has the largest population?<< - ( ) Brazil {{ timely feedback -- explain why an almost correct answer is wrong }} - ( ) Germany - (x) Indonesia - ( ) Russia - - [explanation] - According to September 2014 estimates: - The population of Indonesia is approximately 250 million. - The population of Brazil is approximately 200 million. - The population of Russia is approximately 146 million. - The population of Germany is approximately 81 million. - [explanation] - """) - expect(data).toXMLEqual(""" - -

Multiple choice problems allow learners to select only one option. Learners can see all the options along with the problem text.

- - - - - Brazil timely feedback -- explain why an almost correct answer is wrong - - Germany - Indonesia - Russia - - -
-

Explanation

-

According to September 2014 estimates:

-

The population of Indonesia is approximately 250 million.

-

The population of Brazil is approximately 200 million.

-

The population of Russia is approximately 146 million.

-

The population of Germany is approximately 81 million.

-
-
-
-
- """) - - it 'can do separation if spaces are present around ---', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>The following languages are in the Indo-European family:||There are three correct choices.<< - [x] Urdu - [ ] Finnish - [x] Marathi - [x] French - [ ] Hungarian - - --- - - >>Which of the following countries has the largest population?||You have only choice.<< - ( ) Brazil {{ timely feedback -- explain why an almost correct answer is wrong }} - ( ) Germany - (x) Indonesia - ( ) Russia - """) - expect(data).toXMLEqual(""" - - - - There are three correct choices. - - Urdu - Finnish - Marathi - French - Hungarian - - - - - - You have only choice. - - Brazil - timely feedback -- explain why an almost correct answer is wrong - - Germany - Indonesia - Russia - - - - """) - - it 'can extract question description', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>The following languages are in the Indo-European family:||Choose wisely.<< - [x] Urdu - [ ] Finnish - [x] Marathi - [x] French - [ ] Hungarian - """) - expect(data).toXMLEqual(""" - - - - Choose wisely. - - Urdu - Finnish - Marathi - French - Hungarian - - - - """) - - it 'can handle question and description spanned across multiple lines', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>The following languages - are in the - Indo-European family: - || - first second - third - << - [x] Urdu - [ ] Finnish - [x] Marathi - """) - expect(data).toXMLEqual(""" - - - - first second third - - Urdu - Finnish - Marathi - - - - """) - - it 'will not add empty description', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>The following languages are in the Indo-European family:||<< - [x] Urdu - [ ] Finnish - """) - expect(data).toXMLEqual(""" - - - - - Urdu - Finnish - - - - """) + return it('will not add empty description', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>The following languages are in the Indo-European family:||<< +[x] Urdu +[ ] Finnish\ +`); + return expect(data).toXMLEqual(`\ + + + + + Urdu + Finnish + + +\ +`); + }); + }); +}); diff --git a/common/lib/xmodule/xmodule/js/spec/problem/edit_spec_hint.js b/common/lib/xmodule/xmodule/js/spec/problem/edit_spec_hint.js index 1a9b7aad97..ef21db04ec 100644 --- a/common/lib/xmodule/xmodule/js/spec/problem/edit_spec_hint.js +++ b/common/lib/xmodule/xmodule/js/spec/problem/edit_spec_hint.js @@ -1,996 +1,1036 @@ -# This file tests the parsing of extended-hints, double bracket sections {{ .. }} -# for all sorts of markdown. -describe 'Markdown to xml extended hint dropdown', -> - it 'produces xml', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - Translation between Dropdown and ________ is straightforward. +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +// This file tests the parsing of extended-hints, double bracket sections {{ .. }} +// for all sorts of markdown. +describe('Markdown to xml extended hint dropdown', function() { + it('produces xml', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +Translation between Dropdown and ________ is straightforward. - [[ - (Multiple Choice) {{ Good Job::Yes, multiple choice is the right answer. }} - Text Input {{ No, text input problems don't present options. }} - Numerical Input {{ No, numerical input problems don't present options. }} - ]] +[[ + (Multiple Choice) {{ Good Job::Yes, multiple choice is the right answer. }} + Text Input {{ No, text input problems don't present options. }} + Numerical Input {{ No, numerical input problems don't present options. }} +]] - Clowns have funny _________ to make people laugh. +Clowns have funny _________ to make people laugh. - [[ - dogs {{ NOPE::Not dogs, not cats, not toads }} - (FACES) {{ With lots of makeup, doncha know?}} +[[ + dogs {{ NOPE::Not dogs, not cats, not toads }} + (FACES) {{ With lots of makeup, doncha know?}} - money {{ Clowns don't have any money, of course }} - donkeys {{don't be an ass.}} - -no hint- - ]] - - """) - expect(data).toXMLEqual(""" - -

Translation between Dropdown and ________ is straightforward.

- - - - - - - -

Clowns have funny _________ to make people laugh.

- - - - - - - - - -
- """) - - it 'produces xml with demand hint', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - Translation between Dropdown and ________ is straightforward. - - [[ - (Right) {{ Good Job::yes }} - Wrong 1 {{no}} - Wrong 2 {{ Label::no }} - ]] - - || 0) zero || - || 1) one || - || 2) two || - """) - expect(data).toXMLEqual(""" - - -

Translation between Dropdown and ________ is straightforward.

+ money {{ Clowns don't have any money, of course }} + donkeys {{don't be an ass.}} + -no hint- +]] +\ +`); + return expect(data).toXMLEqual(`\ + +

Translation between Dropdown and ________ is straightforward.

+ - - - - - - - - 0) zero - 1) one - 2) two - -
- """) - - it 'produces xml with single-line markdown syntax', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - A Question ________ is answered. - - [[(Right), Wrong 1, Wrong 2]] - || 0) zero || - || 1) one || - """) - expect(data).toXMLEqual(""" - - -

A Question ________ is answered.

- -
- - - 0) zero - 1) one - -
- """) - - it 'produces xml with fewer newlines', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>q1<< - [[ (aa) {{ hint1 }} - bb - cc {{ hint2 }} ]] - """) - expect(data).toXMLEqual(""" - - - + + + + + +

Clowns have funny _________ to make people laugh.

+ - - - - - - - -
- """) - - it 'produces xml even with lots of whitespace', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>q1<< - [[ - - - aa {{ hint1 }} - - bb {{ hint2 }} - (cc) - - ]] - """) - expect(data).toXMLEqual(""" - - - - - - - - - - - - - """) - -describe 'Markdown to xml extended hint checkbox', -> - it 'produces xml', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>Select all the fruits from the list<< - - [x] Apple {{ selected: You're right that apple is a fruit. }, {unselected: Remember that apple is also a fruit.}} - [ ] Mushroom {{U: You're right that mushrooms aren't fruit}, { selected: Mushroom is a fungus, not a fruit.}} - [x] Grape {{ selected: You're right that grape is a fruit }, {unselected: Remember that grape is also a fruit.}} - [ ] Mustang - [ ] Camero {{S:I don't know what a Camero is but it isn't a fruit.},{U:What is a camero anyway?}} - - - {{ ((A*B)) You're right that apple is a fruit, but there's one you're missing. Also, mushroom is not a fruit.}} - {{ ((B*C)) You're right that grape is a fruit, but there's one you're missing. Also, mushroom is not a fruit. }} - - - >>Select all the vegetables from the list<< - - [ ] Banana {{ selected: No, sorry, a banana is a fruit. }, {unselected: poor banana.}} - [ ] Ice Cream - [ ] Mushroom {{U: You're right that mushrooms aren't vegetables.}, { selected: Mushroom is a fungus, not a vegetable.}} - [x] Brussel Sprout {{S: Brussel sprouts are vegetables.}, {u: Brussel sprout is the only vegetable in this list.}} - - - {{ ((A*B)) Making a banana split? }} - {{ ((B*D)) That will make a horrible dessert: a brussel sprout split? }} - """) - expect(data).toXMLEqual(""" - - - - - Apple - You're right that apple is a fruit. - Remember that apple is also a fruit. - - Mushroom - Mushroom is a fungus, not a fruit. - You're right that mushrooms aren't fruit - - Grape - You're right that grape is a fruit - Remember that grape is also a fruit. - - Mustang - Camero - I don't know what a Camero is but it isn't a fruit. - What is a camero anyway? - - You're right that apple is a fruit, but there's one you're missing. Also, mushroom is not a fruit. - You're right that grape is a fruit, but there's one you're missing. Also, mushroom is not a fruit. - - - - - - - Banana - No, sorry, a banana is a fruit. - poor banana. - - Ice Cream - Mushroom - Mushroom is a fungus, not a vegetable. - You're right that mushrooms aren't vegetables. - - Brussel Sprout - Brussel sprouts are vegetables. - Brussel sprout is the only vegetable in this list. - - Making a banana split? - That will make a horrible dessert: a brussel sprout split? - - - - """) - - it 'produces xml also with demand hints', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>Select all the fruits from the list<< - - [x] Apple {{ selected: You're right that apple is a fruit. }, {unselected: Remember that apple is also a fruit.}} - [ ] Mushroom {{U: You're right that mushrooms aren't fruit}, { selected: Mushroom is a fungus, not a fruit.}} - [x] Grape {{ selected: You're right that grape is a fruit }, {unselected: Remember that grape is also a fruit.}} - [ ] Mustang - [ ] Camero {{S:I don't know what a Camero is but it isn't a fruit.},{U:What is a camero anyway?}} - - {{ ((A*B)) You're right that apple is a fruit, but there's one you're missing. Also, mushroom is not a fruit.}} - {{ ((B*C)) You're right that grape is a fruit, but there's one you're missing. Also, mushroom is not a fruit.}} - - >>Select all the vegetables from the list<< - - [ ] Banana {{ selected: No, sorry, a banana is a fruit. }, {unselected: poor banana.}} - [ ] Ice Cream - [ ] Mushroom {{U: You're right that mushrooms aren't vegatbles}, { selected: Mushroom is a fungus, not a vegetable.}} - [x] Brussel Sprout {{S: Brussel sprouts are vegetables.}, {u: Brussel sprout is the only vegetable in this list.}} - - {{ ((A*B)) Making a banana split? }} - {{ ((B*D)) That will make a horrible dessert: a brussel sprout split? }} - - || Hint one.|| - || Hint two. || - || Hint three. || - """) - expect(data).toXMLEqual(""" - - - - - Apple - You're right that apple is a fruit. - Remember that apple is also a fruit. - - Mushroom - Mushroom is a fungus, not a fruit. - You're right that mushrooms aren't fruit - - Grape - You're right that grape is a fruit - Remember that grape is also a fruit. - - Mustang - Camero - I don't know what a Camero is but it isn't a fruit. - What is a camero anyway? - - You're right that apple is a fruit, but there's one you're missing. Also, mushroom is not a fruit. - You're right that grape is a fruit, but there's one you're missing. Also, mushroom is not a fruit. - - - - - - - Banana - No, sorry, a banana is a fruit. - poor banana. - - Ice Cream - Mushroom - Mushroom is a fungus, not a vegetable. - You're right that mushrooms aren't vegatbles - - Brussel Sprout - Brussel sprouts are vegetables. - Brussel sprout is the only vegetable in this list. - - Making a banana split? - That will make a horrible dessert: a brussel sprout split? - - - - - Hint one. - Hint two. - Hint three. - - - """) - - -describe 'Markdown to xml extended hint multiple choice', -> - it 'produces xml', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>Select the fruit from the list<< - - () Mushroom {{ Mushroom is a fungus, not a fruit.}} - () Potato - (x) Apple {{ OUTSTANDING::Apple is indeed a fruit.}} - - >>Select the vegetables from the list<< - - () Mushroom {{ Mushroom is a fungus, not a vegetable.}} - (x) Potato {{ Potato is a root vegetable. }} - () Apple {{ OOPS::Apple is a fruit.}} - """) - expect(data).toXMLEqual(""" - - - - - Mushroom - Mushroom is a fungus, not a fruit. - - Potato - Apple - Apple is indeed a fruit. - - - - - - - - Mushroom - Mushroom is a fungus, not a vegetable. - - Potato - Potato is a root vegetable. - - Apple - Apple is a fruit. - - - - - """) - - it 'produces xml with demand hints', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>Select the fruit from the list<< - - () Mushroom {{ Mushroom is a fungus, not a fruit.}} - () Potato - (x) Apple {{ OUTSTANDING::Apple is indeed a fruit.}} - - || 0) spaces on previous line. || - || 1) roses are red. || - - >>Select the vegetables from the list<< - - () Mushroom {{ Mushroom is a fungus, not a vegetable.}} - (x) Potato {{ Potato is a root vegetable. }} - () Apple {{ OOPS::Apple is a fruit.}} - - || 2) where are the lions? || - - """) - expect(data).toXMLEqual(""" - - - - - Mushroom - Mushroom is a fungus, not a fruit. - - Potato - Apple - Apple is indeed a fruit. - - - - - - - - Mushroom - Mushroom is a fungus, not a vegetable. - - Potato - Potato is a root vegetable. - - Apple - Apple is a fruit. - - - - - - 0) spaces on previous line. - 1) roses are red. - 2) where are the lions? - - - """) - - -describe 'Markdown to xml extended hint text input', -> - it 'produces xml', -> - data = MarkdownEditingDescriptor.markdownToXml(""">>In which country would you find the city of Paris?<< - = France {{ BRAVO::Viva la France! }} - - """) - expect(data).toXMLEqual(""" - - - - Viva la France! - - - - - - """) - - it 'produces xml with or=', -> - data = MarkdownEditingDescriptor.markdownToXml(""">>Where Paris?<< - = France {{ BRAVO::hint1}} - or= USA {{ meh::hint2 }} - - """) - expect(data).toXMLEqual(""" - - - - hint1 - hint2 - - - - - - - """) - - it 'produces xml with not=', -> - data = MarkdownEditingDescriptor.markdownToXml(""">>Revenge is a dish best served<< - = cold {{khaaaaaan!}} - not= warm {{feedback2}} - - """) - expect(data).toXMLEqual(""" - - - - khaaaaaan! - feedback2 - - - - - - """) - - it 'produces xml with s=', -> - data = MarkdownEditingDescriptor.markdownToXml(""">>q<< - s= 2 {{feedback1}} - - """) - expect(data).toXMLEqual(""" - - - - feedback1 - - - - - - """) - - it 'produces xml with = and or= and not=', -> - data = MarkdownEditingDescriptor.markdownToXml(""">>q<< - = aaa - or= bbb {{feedback1}} - not= no {{feedback2}} - or= ccc - - """) - expect(data).toXMLEqual(""" - - - - feedback1 - - feedback2 - - - - - - - """) - - it 'produces xml with s= and or=', -> - data = MarkdownEditingDescriptor.markdownToXml(""">>q<< - s= 2 {{feedback1}} - or= bbb {{feedback2}} - or= ccc - - """) - expect(data).toXMLEqual(""" - - - - feedback1 - feedback2 - - - - - - - - """) - - it 'produces xml with each = making a new question', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>q<< - = aaa - or= bbb - s= ccc - """) - expect(data).toXMLEqual(""" - - - - - - - - - - - """) - - it 'produces xml with each = making a new question amid blank lines and paragraphs', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - paragraph - >>q<< - = aaa - - or= bbb - s= ccc - - paragraph 2 - - """) - expect(data).toXMLEqual(""" - -

paragraph

- - - - - - - - -

paragraph 2

-
- """) - - it 'produces xml without a question when or= is just hung out there by itself', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - paragraph - >>q<< - or= aaa - paragraph 2 - - """) - expect(data).toXMLEqual(""" - -

paragraph

- -

or= aaa

-

paragraph 2

-
- """) - - it 'produces xml with each = with feedback making a new question', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>q<< - s= aaa - or= bbb {{feedback1}} - = ccc {{feedback2}} - - """) - expect(data).toXMLEqual(""" - - - - - feedback1 - - - - - feedback2 - - - - """) - - it 'produces xml with demand hints', -> - data = MarkdownEditingDescriptor.markdownToXml(""">>Where Paris?<< - = France {{ BRAVO::hint1 }} - - || There are actually two countries with cities named Paris. || - || Paris is the capital of one of those countries. || - - """) - expect(data).toXMLEqual(""" - - - - hint1 - - - - - There are actually two countries with cities named Paris. - Paris is the capital of one of those countries. - - """) - - -describe 'Markdown to xml extended hint numeric input', -> - it 'produces xml', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>Enter the numerical value of Pi:<< - = 3.14159 +- .02 {{ Pie for everyone! }} - - >>Enter the approximate value of 502*9:<< - = 4518 +- 15% {{PIE:: No pie for you!}} - - >>Enter the number of fingers on a human hand<< - = 5 - - """) - expect(data).toXMLEqual(""" - - - - - - Pie for everyone! - - - - - - - No pie for you! - - - - - - - - """) - - # The output xml here shows some of the quirks of how historical markdown parsing does or does not put - # in blank lines. - it 'numeric input with hints and demand hints', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>text1<< - = 1 {{ hint1 }} - || hintA || - >>text2<< - = 2 {{ hint2 }} - - || hintB || - - """) - expect(data).toXMLEqual(""" - - - - - hint1 - - - - - hint2 - - - - hintA - hintB - - - """) - - -describe 'Markdown to xml extended hint with multiline hints', -> - it 'produces xml', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>Checkboxes<< - - [x] A {{ - selected: aaa }, - {unselected:bbb}} - [ ] B {{U: c}, { - selected: d.}} - - {{ ((A*B)) A*B hint}} - - >>What is 1 + 1?<< - = 2 {{ part one, and - part two - }} - - >>hello?<< - = hello {{ - hello - hint - }} - - >>multiple choice<< - (x) AA{{hint1}} - () BB {{ - hint2 - }} - ( ) CC {{ hint3 - }} - - >>dropdown<< - [[ - W1 {{ - no }} - W2 {{ - nope}} - (C1) {{ yes - }} - ]] - - || aaa || - ||bbb|| - || ccc || - - """) - expect(data).toXMLEqual(""" - - - - - A - aaa - bbb - - B - d. - c - - A*B hint - - - - - - - part one, and part two - - - - - hello hint - - - - - - - AA - hint1 - - BB - hint2 - - CC - hint3 - - - - - - - - - - - - - - - aaa - bbb - ccc - - - """) - -describe 'Markdown to xml extended hint with tricky syntax cases', -> - # I'm entering this as utf-8 in this file. - # I cannot find a way to set the encoding for .coffee files but it seems to work. - it 'produces xml with unicode', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>á and Ø<< - - (x) Ø{{Ø}} - () BB - - || Ø || - - """) - expect(data).toXMLEqual(""" - - - - - Ø - Ø - - BB - - - - - Ø - - - """) - - it 'produces xml with quote-type characters', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>"quotes" aren't `fun`<< - () "hello" {{ isn't }} - (x) "isn't" {{ "hello" }} - - """) - expect(data).toXMLEqual(""" - - - - - "hello" - isn't - - "isn't" - "hello" - - - - - """) - - it 'produces xml with almost but not quite multiple choice syntax', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>q1<< - this (x) - () a {{ (hint) }} - (x) b - that (y) - """) - expect(data).toXMLEqual(""" - - - -

this (x)

- - a (hint) - - b - -

that (y)

-
- - -
- """) - - # An incomplete checkbox hint passes through to cue the author - it 'produce xml with almost but not quite checkboxgroup syntax', -> - data = MarkdownEditingDescriptor.markdownToXml(""" - >>q1<< - this [x] - [ ] a [square] - [x] b {{ this hint passes through }} - that [] - """) - expect(data).toXMLEqual(""" - + + + + + + +
+
\ +`); + }); + + it('produces xml with demand hint', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +Translation between Dropdown and ________ is straightforward. + +[[ + (Right) {{ Good Job::yes }} + Wrong 1 {{no}} + Wrong 2 {{ Label::no }} +]] + +|| 0) zero || +|| 1) one || +|| 2) two ||\ +`); + return expect(data).toXMLEqual(`\ + + +

Translation between Dropdown and ________ is straightforward.

+ + + + + +
+ + + 0) zero + 1) one + 2) two + +
\ +`); + }); + + it('produces xml with single-line markdown syntax', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +A Question ________ is answered. + +[[(Right), Wrong 1, Wrong 2]] +|| 0) zero || +|| 1) one ||\ +`); + return expect(data).toXMLEqual(`\ + + +

A Question ________ is answered.

+ +
+ + + 0) zero + 1) one + +
\ +`); + }); + + it('produces xml with fewer newlines', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>q1<< +[[ (aa) {{ hint1 }} + bb + cc {{ hint2 }} ]]\ +`); + return expect(data).toXMLEqual(`\ + + + + + + + + + + + +\ +`); + }); + + return it('produces xml even with lots of whitespace', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>q1<< +[[ + + + aa {{ hint1 }} + + bb {{ hint2 }} + (cc) + + ]]\ +`); + return expect(data).toXMLEqual(`\ + + + + + + + + + + + +\ +`); + }); +}); + +describe('Markdown to xml extended hint checkbox', function() { + it('produces xml', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>Select all the fruits from the list<< + +[x] Apple {{ selected: You're right that apple is a fruit. }, {unselected: Remember that apple is also a fruit.}} +[ ] Mushroom {{U: You're right that mushrooms aren't fruit}, { selected: Mushroom is a fungus, not a fruit.}} +[x] Grape {{ selected: You're right that grape is a fruit }, {unselected: Remember that grape is also a fruit.}} +[ ] Mustang +[ ] Camero {{S:I don't know what a Camero is but it isn't a fruit.},{U:What is a camero anyway?}} + + +{{ ((A*B)) You're right that apple is a fruit, but there's one you're missing. Also, mushroom is not a fruit.}} +{{ ((B*C)) You're right that grape is a fruit, but there's one you're missing. Also, mushroom is not a fruit. }} + + +>>Select all the vegetables from the list<< + +[ ] Banana {{ selected: No, sorry, a banana is a fruit. }, {unselected: poor banana.}} +[ ] Ice Cream +[ ] Mushroom {{U: You're right that mushrooms aren't vegetables.}, { selected: Mushroom is a fungus, not a vegetable.}} +[x] Brussel Sprout {{S: Brussel sprouts are vegetables.}, {u: Brussel sprout is the only vegetable in this list.}} + + +{{ ((A*B)) Making a banana split? }} +{{ ((B*D)) That will make a horrible dessert: a brussel sprout split? }}\ +`); + return expect(data).toXMLEqual(`\ + + - -

this [x]

- - a [square] - b {{ this hint passes through }} - -

that []

+ + Apple + You're right that apple is a fruit. + Remember that apple is also a fruit. + + Mushroom + Mushroom is a fungus, not a fruit. + You're right that mushrooms aren't fruit + + Grape + You're right that grape is a fruit + Remember that grape is also a fruit. + + Mustang + Camero + I don't know what a Camero is but it isn't a fruit. + What is a camero anyway? + + You're right that apple is a fruit, but there's one you're missing. Also, mushroom is not a fruit. + You're right that grape is a fruit, but there's one you're missing. Also, mushroom is not a fruit. +
+ + + + Banana + No, sorry, a banana is a fruit. + poor banana. + + Ice Cream + Mushroom + Mushroom is a fungus, not a vegetable. + You're right that mushrooms aren't vegetables. + + Brussel Sprout + Brussel sprouts are vegetables. + Brussel sprout is the only vegetable in this list. + + Making a banana split? + That will make a horrible dessert: a brussel sprout split? + + +
\ +`); + }); -
- """) + return it('produces xml also with demand hints', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>Select all the fruits from the list<< - # It's sort of a pain to edit DOS line endings without some editor or other "fixing" them - # for you. Therefore, we construct DOS line endings on the fly just for the test. - it 'produces xml with DOS \r\n line endings', -> - markdown = """ - >>q22<< +[x] Apple {{ selected: You're right that apple is a fruit. }, {unselected: Remember that apple is also a fruit.}} +[ ] Mushroom {{U: You're right that mushrooms aren't fruit}, { selected: Mushroom is a fungus, not a fruit.}} +[x] Grape {{ selected: You're right that grape is a fruit }, {unselected: Remember that grape is also a fruit.}} +[ ] Mustang +[ ] Camero {{S:I don't know what a Camero is but it isn't a fruit.},{U:What is a camero anyway?}} - [[ - (x) {{ hintx - these - span - }} +{{ ((A*B)) You're right that apple is a fruit, but there's one you're missing. Also, mushroom is not a fruit.}} +{{ ((B*C)) You're right that grape is a fruit, but there's one you're missing. Also, mushroom is not a fruit.}} - yy {{ meh::hinty }} - zzz {{ hintz }} - ]] - """ - markdown = markdown.replace(/\n/g, '\r\n') # make DOS line endings - data = MarkdownEditingDescriptor.markdownToXml(markdown) - expect(data).toXMLEqual(""" - +>>Select all the vegetables from the list<< + +[ ] Banana {{ selected: No, sorry, a banana is a fruit. }, {unselected: poor banana.}} +[ ] Ice Cream +[ ] Mushroom {{U: You're right that mushrooms aren't vegatbles}, { selected: Mushroom is a fungus, not a vegetable.}} +[x] Brussel Sprout {{S: Brussel sprouts are vegetables.}, {u: Brussel sprout is the only vegetable in this list.}} + +{{ ((A*B)) Making a banana split? }} +{{ ((B*D)) That will make a horrible dessert: a brussel sprout split? }} + +|| Hint one.|| +|| Hint two. || +|| Hint three. ||\ +`); + return expect(data).toXMLEqual(`\ + + + + + Apple + You're right that apple is a fruit. + Remember that apple is also a fruit. + + Mushroom + Mushroom is a fungus, not a fruit. + You're right that mushrooms aren't fruit + + Grape + You're right that grape is a fruit + Remember that grape is also a fruit. + + Mustang + Camero + I don't know what a Camero is but it isn't a fruit. + What is a camero anyway? + + You're right that apple is a fruit, but there's one you're missing. Also, mushroom is not a fruit. + You're right that grape is a fruit, but there's one you're missing. Also, mushroom is not a fruit. + + + + + + + Banana + No, sorry, a banana is a fruit. + poor banana. + + Ice Cream + Mushroom + Mushroom is a fungus, not a vegetable. + You're right that mushrooms aren't vegatbles + + Brussel Sprout + Brussel sprouts are vegetables. + Brussel sprout is the only vegetable in this list. + + Making a banana split? + That will make a horrible dessert: a brussel sprout split? + + + + + Hint one. + Hint two. + Hint three. + +\ +`); + }); +}); + + +describe('Markdown to xml extended hint multiple choice', function() { + it('produces xml', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>Select the fruit from the list<< + +() Mushroom {{ Mushroom is a fungus, not a fruit.}} +() Potato +(x) Apple {{ OUTSTANDING::Apple is indeed a fruit.}} + +>>Select the vegetables from the list<< + +() Mushroom {{ Mushroom is a fungus, not a vegetable.}} +(x) Potato {{ Potato is a root vegetable. }} +() Apple {{ OOPS::Apple is a fruit.}}\ +`); + return expect(data).toXMLEqual(`\ + + + + + Mushroom + Mushroom is a fungus, not a fruit. + + Potato + Apple + Apple is indeed a fruit. + + + + + + + + Mushroom + Mushroom is a fungus, not a vegetable. + + Potato + Potato is a root vegetable. + + Apple + Apple is a fruit. + + + +\ +`); + }); + + return it('produces xml with demand hints', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>Select the fruit from the list<< + +() Mushroom {{ Mushroom is a fungus, not a fruit.}} +() Potato +(x) Apple {{ OUTSTANDING::Apple is indeed a fruit.}} + +|| 0) spaces on previous line. || +|| 1) roses are red. || + +>>Select the vegetables from the list<< + +() Mushroom {{ Mushroom is a fungus, not a vegetable.}} +(x) Potato {{ Potato is a root vegetable. }} +() Apple {{ OOPS::Apple is a fruit.}} + +|| 2) where are the lions? || +\ +`); + return expect(data).toXMLEqual(`\ + + + + + Mushroom + Mushroom is a fungus, not a fruit. + + Potato + Apple + Apple is indeed a fruit. + + + + + + + + Mushroom + Mushroom is a fungus, not a vegetable. + + Potato + Potato is a root vegetable. + + Apple + Apple is a fruit. + + + + + + 0) spaces on previous line. + 1) roses are red. + 2) where are the lions? + +\ +`); + }); +}); + + +describe('Markdown to xml extended hint text input', function() { + it('produces xml', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`>>In which country would you find the city of Paris?<< += France {{ BRAVO::Viva la France! }} +\ +`); + return expect(data).toXMLEqual(`\ + + + +Viva la France! + + + + +\ +`); + }); + + it('produces xml with or=', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`>>Where Paris?<< += France {{ BRAVO::hint1}} +or= USA {{ meh::hint2 }} +\ +`); + return expect(data).toXMLEqual(`\ + + + +hint1 + hint2 + + + + + +\ +`); + }); + + it('produces xml with not=', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`>>Revenge is a dish best served<< += cold {{khaaaaaan!}} +not= warm {{feedback2}} +\ +`); + return expect(data).toXMLEqual(`\ + + + +khaaaaaan! + feedback2 + + + + +\ +`); + }); + + it('produces xml with s=', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`>>q<< +s= 2 {{feedback1}} +\ +`); + return expect(data).toXMLEqual(`\ + + + +feedback1 + + + + +\ +`); + }); + + it('produces xml with = and or= and not=', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`>>q<< += aaa +or= bbb {{feedback1}} +not= no {{feedback2}} +or= ccc +\ +`); + return expect(data).toXMLEqual(`\ + + + +feedback1 + + feedback2 + + + + + +\ +`); + }); + + it('produces xml with s= and or=', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`>>q<< +s= 2 {{feedback1}} +or= bbb {{feedback2}} +or= ccc +\ +`); + return expect(data).toXMLEqual(`\ + + + +feedback1 + feedback2 + + + + + + +\ +`); + }); + + it('produces xml with each = making a new question', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>q<< += aaa +or= bbb +s= ccc\ +`); + return expect(data).toXMLEqual(`\ + + + + + + + + + +\ +`); + }); + + it('produces xml with each = making a new question amid blank lines and paragraphs', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +paragraph +>>q<< += aaa + +or= bbb +s= ccc + +paragraph 2 +\ +`); + return expect(data).toXMLEqual(`\ + +

paragraph

+ + + + + + + + +

paragraph 2

+
\ +`); + }); + + it('produces xml without a question when or= is just hung out there by itself', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +paragraph +>>q<< +or= aaa +paragraph 2 +\ +`); + return expect(data).toXMLEqual(`\ + +

paragraph

+ +

or= aaa

+

paragraph 2

+
\ +`); + }); + + it('produces xml with each = with feedback making a new question', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>q<< +s= aaa +or= bbb {{feedback1}} += ccc {{feedback2}} +\ +`); + return expect(data).toXMLEqual(`\ + + + + + feedback1 + + + + + feedback2 + + +\ +`); + }); + + return it('produces xml with demand hints', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`>>Where Paris?<< += France {{ BRAVO::hint1 }} + +|| There are actually two countries with cities named Paris. || +|| Paris is the capital of one of those countries. || +\ +`); + return expect(data).toXMLEqual(`\ + + + +hint1 + + + + + There are actually two countries with cities named Paris. + Paris is the capital of one of those countries. + +`); + }); +}); + + +describe('Markdown to xml extended hint numeric input', function() { + it('produces xml', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>Enter the numerical value of Pi:<< += 3.14159 +- .02 {{ Pie for everyone! }} + +>>Enter the approximate value of 502*9:<< += 4518 +- 15% {{PIE:: No pie for you!}} + +>>Enter the number of fingers on a human hand<< += 5 +\ +`); + return expect(data).toXMLEqual(`\ + + + + + + Pie for everyone! + + + + + + + No pie for you! + + + + + + +\ +`); + }); + + // The output xml here shows some of the quirks of how historical markdown parsing does or does not put + // in blank lines. + return it('numeric input with hints and demand hints', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>text1<< += 1 {{ hint1 }} +|| hintA || +>>text2<< += 2 {{ hint2 }} + +|| hintB || +\ +`); + return expect(data).toXMLEqual(`\ + + + + + hint1 + + + + + hint2 + + + + hintA + hintB + +\ +`); + }); +}); + + +describe('Markdown to xml extended hint with multiline hints', () => + it('produces xml', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>Checkboxes<< + +[x] A {{ +selected: aaa }, +{unselected:bbb}} +[ ] B {{U: c}, { +selected: d.}} + +{{ ((A*B)) A*B hint}} + +>>What is 1 + 1?<< += 2 {{ part one, and + part two + }} + +>>hello?<< += hello {{ +hello +hint +}} + +>>multiple choice<< +(x) AA{{hint1}} +() BB {{ + hint2 +}} +( ) CC {{ hint3 +}} + +>>dropdown<< +[[ + W1 {{ + no }} + W2 {{ + nope}} + (C1) {{ yes + }} +]] + +|| aaa || +||bbb|| +|| ccc || +\ +`); + return expect(data).toXMLEqual(`\ + + + + + A + aaa + bbb + + B + d. + c + + A*B hint + + + + + + + part one, and part two + + + + + hello hint + + + + + + + AA + hint1 + + BB + hint2 + + CC + hint3 + + + + + - - - - - - + + + + + + + aaa + bbb + ccc + +\ +`); + }) +); -
- """) +describe('Markdown to xml extended hint with tricky syntax cases', function() { + // I'm entering this as utf-8 in this file. + // I cannot find a way to set the encoding for .coffee files but it seems to work. + it('produces xml with unicode', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>á and Ø<< + +(x) Ø{{Ø}} +() BB + +|| Ø || +\ +`); + return expect(data).toXMLEqual(`\ + + + + + Ø + Ø + + BB + + + + + Ø + +\ +`); + }); + + it('produces xml with quote-type characters', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>"quotes" aren't \`fun\`<< +() "hello" {{ isn't }} +(x) "isn't" {{ "hello" }} +\ +`); + return expect(data).toXMLEqual(`\ + + + + + "hello" + isn't + + "isn't" + "hello" + + + +\ +`); + }); + + it('produces xml with almost but not quite multiple choice syntax', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>q1<< +this (x) +() a {{ (hint) }} +(x) b +that (y)\ +`); + return expect(data).toXMLEqual(`\ + + + +

this (x)

+ + a (hint) + + b + +

that (y)

+
+ + +
\ +`); + }); + + // An incomplete checkbox hint passes through to cue the author + it('produce xml with almost but not quite checkboxgroup syntax', function() { + const data = MarkdownEditingDescriptor.markdownToXml(`\ +>>q1<< +this [x] +[ ] a [square] +[x] b {{ this hint passes through }} +that []\ +`); + return expect(data).toXMLEqual(`\ + + + +

this [x]

+ + a [square] + b {{ this hint passes through }} + +

that []

+
+ + +
\ +`); + }); + + // It's sort of a pain to edit DOS line endings without some editor or other "fixing" them + // for you. Therefore, we construct DOS line endings on the fly just for the test. + return it('produces xml with DOS \r\n line endings', function() { + let markdown = `\ +>>q22<< + +[[ + (x) {{ hintx + these + span + }} + + yy {{ meh::hinty }} + zzz {{ hintz }} +]]\ +`; + markdown = markdown.replace(/\n/g, '\r\n'); // make DOS line endings + const data = MarkdownEditingDescriptor.markdownToXml(markdown); + return expect(data).toXMLEqual(`\ + + + + + + + + + + + +\ +`); + }); +}); diff --git a/common/lib/xmodule/xmodule/js/spec/tabs/edit.js b/common/lib/xmodule/xmodule/js/spec/tabs/edit.js index ae73009bf3..79c6762c26 100644 --- a/common/lib/xmodule/xmodule/js/spec/tabs/edit.js +++ b/common/lib/xmodule/xmodule/js/spec/tabs/edit.js @@ -1,90 +1,111 @@ -describe "TabsEditingDescriptor", -> - beforeEach -> - @isInactiveClass = "is-inactive" - @isCurrent = "current" - loadFixtures 'tabs-edit.html' - @descriptor = new TabsEditingDescriptor($('.xblock')) - @html_id = 'test_id' - @tab_0_switch = jasmine.createSpy('tab_0_switch'); - @tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate'); - @tab_1_switch = jasmine.createSpy('tab_1_switch'); - @tab_1_modelUpdate = jasmine.createSpy('tab_1_modelUpdate'); - TabsEditingDescriptor.Model.addModelUpdate(@html_id, 'Tab 0 Editor', @tab_0_modelUpdate) - TabsEditingDescriptor.Model.addOnSwitch(@html_id, 'Tab 0 Editor', @tab_0_switch) - TabsEditingDescriptor.Model.addModelUpdate(@html_id, 'Tab 1 Transcripts', @tab_1_modelUpdate) - TabsEditingDescriptor.Model.addOnSwitch(@html_id, 'Tab 1 Transcripts', @tab_1_switch) +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +describe("TabsEditingDescriptor", function() { + beforeEach(function() { + this.isInactiveClass = "is-inactive"; + this.isCurrent = "current"; + loadFixtures('tabs-edit.html'); + this.descriptor = new TabsEditingDescriptor($('.xblock')); + this.html_id = 'test_id'; + this.tab_0_switch = jasmine.createSpy('tab_0_switch'); + this.tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate'); + this.tab_1_switch = jasmine.createSpy('tab_1_switch'); + this.tab_1_modelUpdate = jasmine.createSpy('tab_1_modelUpdate'); + TabsEditingDescriptor.Model.addModelUpdate(this.html_id, 'Tab 0 Editor', this.tab_0_modelUpdate); + TabsEditingDescriptor.Model.addOnSwitch(this.html_id, 'Tab 0 Editor', this.tab_0_switch); + TabsEditingDescriptor.Model.addModelUpdate(this.html_id, 'Tab 1 Transcripts', this.tab_1_modelUpdate); + TabsEditingDescriptor.Model.addOnSwitch(this.html_id, 'Tab 1 Transcripts', this.tab_1_switch); - spyOn($.fn, 'hide').and.callThrough() - spyOn($.fn, 'show').and.callThrough() - spyOn(TabsEditingDescriptor.Model, 'initialize') - spyOn(TabsEditingDescriptor.Model, 'updateValue') + spyOn($.fn, 'hide').and.callThrough(); + spyOn($.fn, 'show').and.callThrough(); + spyOn(TabsEditingDescriptor.Model, 'initialize'); + return spyOn(TabsEditingDescriptor.Model, 'updateValue'); + }); - afterEach -> - TabsEditingDescriptor.Model.modules= {} + afterEach(() => TabsEditingDescriptor.Model.modules= {}); - describe "constructor", -> - it "first tab should be visible", -> - expect(@descriptor.$tabs.first()).toHaveClass(@isCurrent) - expect(@descriptor.$content.first()).not.toHaveClass(@isInactiveClass) + describe("constructor", () => + it("first tab should be visible", function() { + expect(this.descriptor.$tabs.first()).toHaveClass(this.isCurrent); + return expect(this.descriptor.$content.first()).not.toHaveClass(this.isInactiveClass); + }) + ); - describe "onSwitchEditor", -> - it "switching tabs changes styles", -> - @descriptor.$tabs.eq(1).trigger("click") - expect(@descriptor.$tabs.eq(0)).not.toHaveClass(@isCurrent) - expect(@descriptor.$content.eq(0)).toHaveClass(@isInactiveClass) - expect(@descriptor.$tabs.eq(1)).toHaveClass(@isCurrent) - expect(@descriptor.$content.eq(1)).not.toHaveClass(@isInactiveClass) - expect(@tab_1_switch).toHaveBeenCalled() + describe("onSwitchEditor", function() { + it("switching tabs changes styles", function() { + this.descriptor.$tabs.eq(1).trigger("click"); + expect(this.descriptor.$tabs.eq(0)).not.toHaveClass(this.isCurrent); + expect(this.descriptor.$content.eq(0)).toHaveClass(this.isInactiveClass); + expect(this.descriptor.$tabs.eq(1)).toHaveClass(this.isCurrent); + expect(this.descriptor.$content.eq(1)).not.toHaveClass(this.isInactiveClass); + return expect(this.tab_1_switch).toHaveBeenCalled(); + }); - it "if click on current tab, nothing should happen", -> - spyOn($.fn, 'trigger').and.callThrough() - currentTab = @descriptor.$tabs.filter('.' + @isCurrent) - @descriptor.$tabs.eq(0).trigger("click") - expect(@descriptor.$tabs.filter('.' + @isCurrent)).toEqual(currentTab) - expect($.fn.trigger.calls.count()).toEqual(1) + it("if click on current tab, nothing should happen", function() { + spyOn($.fn, 'trigger').and.callThrough(); + const currentTab = this.descriptor.$tabs.filter(`.${this.isCurrent}`); + this.descriptor.$tabs.eq(0).trigger("click"); + expect(this.descriptor.$tabs.filter(`.${this.isCurrent}`)).toEqual(currentTab); + return expect($.fn.trigger.calls.count()).toEqual(1); + }); - it "onSwitch function call", -> - @descriptor.$tabs.eq(1).trigger("click") - expect(TabsEditingDescriptor.Model.updateValue).toHaveBeenCalled() - expect(@tab_1_switch).toHaveBeenCalled() + return it("onSwitch function call", function() { + this.descriptor.$tabs.eq(1).trigger("click"); + expect(TabsEditingDescriptor.Model.updateValue).toHaveBeenCalled(); + return expect(this.tab_1_switch).toHaveBeenCalled(); + }); + }); - describe "save", -> - it "function for current tab should be called", -> - @descriptor.$tabs.eq(1).trigger("click") - data = @descriptor.save().data - expect(@tab_1_modelUpdate).toHaveBeenCalled() + return describe("save", function() { + it("function for current tab should be called", function() { + this.descriptor.$tabs.eq(1).trigger("click"); + const { data } = this.descriptor.save(); + return expect(this.tab_1_modelUpdate).toHaveBeenCalled(); + }); - it "detach click event", -> - spyOn($.fn, "off") - @descriptor.save() - expect($.fn.off).toHaveBeenCalledWith( + return it("detach click event", function() { + spyOn($.fn, "off"); + this.descriptor.save(); + return expect($.fn.off).toHaveBeenCalledWith( 'click', '.editor-tabs .tab', - @descriptor.onSwitchEditor - ) + this.descriptor.onSwitchEditor + ); + }); + }); +}); -describe "TabsEditingDescriptor special save cases", -> - beforeEach -> - @isInactiveClass = "is-inactive" - @isCurrent = "current" - loadFixtures 'tabs-edit.html' - @descriptor = new window.TabsEditingDescriptor($('.xblock')) - @html_id = 'test_id' +describe("TabsEditingDescriptor special save cases", function() { + beforeEach(function() { + this.isInactiveClass = "is-inactive"; + this.isCurrent = "current"; + loadFixtures('tabs-edit.html'); + this.descriptor = new window.TabsEditingDescriptor($('.xblock')); + return this.html_id = 'test_id'; + }); - describe "save", -> - it "case: no init", -> - data = @descriptor.save().data - expect(data).toEqual(null) + return describe("save", function() { + it("case: no init", function() { + const { data } = this.descriptor.save(); + return expect(data).toEqual(null); + }); - it "case: no function in model update", -> - TabsEditingDescriptor.Model.initialize(@html_id) - data = @descriptor.save().data - expect(data).toEqual(null) + it("case: no function in model update", function() { + TabsEditingDescriptor.Model.initialize(this.html_id); + const { data } = this.descriptor.save(); + return expect(data).toEqual(null); + }); - it "case: no function in model update, but value presented", -> - @tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate').and.returnValue(1) - TabsEditingDescriptor.Model.addModelUpdate(@html_id, 'Tab 0 Editor', @tab_0_modelUpdate) - @descriptor.$tabs.eq(1).trigger("click") - expect(@tab_0_modelUpdate).toHaveBeenCalled() - data = @descriptor.save().data - expect(data).toEqual(1) + return it("case: no function in model update, but value presented", function() { + this.tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate').and.returnValue(1); + TabsEditingDescriptor.Model.addModelUpdate(this.html_id, 'Tab 0 Editor', this.tab_0_modelUpdate); + this.descriptor.$tabs.eq(1).trigger("click"); + expect(this.tab_0_modelUpdate).toHaveBeenCalled(); + const { data } = this.descriptor.save(); + return expect(data).toEqual(1); + }); + }); +}); diff --git a/common/static/coffee/spec/jquery.immediateDescendents_spec.js b/common/static/coffee/spec/jquery.immediateDescendents_spec.js index d16bc29c20..6d99bc145e 100644 --- a/common/static/coffee/spec/jquery.immediateDescendents_spec.js +++ b/common/static/coffee/spec/jquery.immediateDescendents_spec.js @@ -1,26 +1,38 @@ -describe "$.immediateDescendents", -> - beforeEach -> - setFixtures """ -
-
-
-
-
-
-
-
- """ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +describe("$.immediateDescendents", function() { + beforeEach(function() { + setFixtures(`\ +
+
+
+
+
+
+
+
\ +` + ); - @descendents = $('#jasmine-fixtures').immediateDescendents(".xblock").get() + return this.descendents = $('#jasmine-fixtures').immediateDescendents(".xblock").get(); + }); - it "finds non-immediate children", -> - expect(@descendents).toContain($('#grandchild').get(0)) + it("finds non-immediate children", function() { + return expect(this.descendents).toContain($('#grandchild').get(0)); + }); - it "finds immediate children", -> - expect(@descendents).toContain($('#child').get(0)) + it("finds immediate children", function() { + return expect(this.descendents).toContain($('#child').get(0)); + }); - it "skips nested descendents", -> - expect(@descendents).not.toContain($('#nested').get(0)) + it("skips nested descendents", function() { + return expect(this.descendents).not.toContain($('#nested').get(0)); + }); - it "finds 2 children", -> - expect(@descendents.length).toBe(2) \ No newline at end of file + return it("finds 2 children", function() { + return expect(this.descendents.length).toBe(2); + }); +}); \ No newline at end of file diff --git a/lms/static/coffee/spec/calculator_spec.js b/lms/static/coffee/spec/calculator_spec.js index 91d69902e1..87159ae0ad 100644 --- a/lms/static/coffee/spec/calculator_spec.js +++ b/lms/static/coffee/spec/calculator_spec.js @@ -1,353 +1,435 @@ -describe 'Calculator', -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +describe('Calculator', function() { - KEY = - TAB : 9 - ENTER : 13 - ALT : 18 - ESC : 27 - SPACE : 32 - LEFT : 37 - UP : 38 - RIGHT : 39 + const KEY = { + TAB : 9, + ENTER : 13, + ALT : 18, + ESC : 27, + SPACE : 32, + LEFT : 37, + UP : 38, + RIGHT : 39, DOWN : 40 + }; - beforeEach -> - loadFixtures 'coffee/fixtures/calculator.html' - @calculator = new Calculator + beforeEach(function() { + loadFixtures('coffee/fixtures/calculator.html'); + return this.calculator = new Calculator; + }); - describe 'bind', -> - it 'bind the calculator button', -> - expect($('.calc')).toHandleWith 'click', @calculator.toggle + describe('bind', function() { + it('bind the calculator button', function() { + return expect($('.calc')).toHandleWith('click', this.calculator.toggle); + }); - it 'bind key up on calculator', -> - expect($('#calculator_wrapper')).toHandle 'keyup', @calculator.handleKeyUpOnHint + it('bind key up on calculator', function() { + return expect($('#calculator_wrapper')).toHandle('keyup', this.calculator.handleKeyUpOnHint); + }); - it 'bind the help button', -> - # This events is bind by $.click() - expect($('#calculator_hint')).toHandle 'click' + it('bind the help button', () => + // This events is bind by $.click() + expect($('#calculator_hint')).toHandle('click') + ); - it 'bind the calculator submit', -> - expect($('form#calculator')).toHandleWith 'submit', @calculator.calculate + it('bind the calculator submit', function() { + return expect($('form#calculator')).toHandleWith('submit', this.calculator.calculate); + }); - xit 'prevent default behavior on form submit', -> - jasmine.stubRequests() - $('form#calculator').submit (e) -> - expect(e.isDefaultPrevented()).toBeTruthy() - e.preventDefault() - $('form#calculator').submit() + return xit('prevent default behavior on form submit', function() { + jasmine.stubRequests(); + $('form#calculator').submit(function(e) { + expect(e.isDefaultPrevented()).toBeTruthy(); + return e.preventDefault(); + }); + return $('form#calculator').submit(); + }); + }); - describe 'toggle', -> - it 'focuses the input when toggled', (done)-> + describe('toggle', function() { + it('focuses the input when toggled', function(done){ - self = this - focus = ()-> - deferred = $.Deferred() + const self = this; + const focus = function(){ + const deferred = $.Deferred(); - # Since the focus is called asynchronously, we need to - # wait until focus() is called. - spyOn($.fn, 'focus').and.callFake (elementName) -> - deferred.resolve() + // Since the focus is called asynchronously, we need to + // wait until focus() is called. + spyOn($.fn, 'focus').and.callFake(elementName => deferred.resolve()); - self.calculator.toggle(jQuery.Event("click")) + self.calculator.toggle(jQuery.Event("click")); - deferred.promise() + return deferred.promise(); + }; - focus().then( - -> - expect($('#calculator_wrapper #calculator_input').focus).toHaveBeenCalled() - ).always(done) + return focus().then( + () => expect($('#calculator_wrapper #calculator_input').focus).toHaveBeenCalled()).always(done); + }); - it 'toggle the close button on the calculator button', -> - @calculator.toggle(jQuery.Event("click")) - expect($('.calc')).toHaveClass('closed') + return it('toggle the close button on the calculator button', function() { + this.calculator.toggle(jQuery.Event("click")); + expect($('.calc')).toHaveClass('closed'); - @calculator.toggle(jQuery.Event("click")) - expect($('.calc')).not.toHaveClass('closed') + this.calculator.toggle(jQuery.Event("click")); + return expect($('.calc')).not.toHaveClass('closed'); + }); + }); - describe 'showHint', -> - it 'show the help overlay', -> - @calculator.showHint() - expect($('.help')).toHaveClass('shown') - expect($('.help')).toHaveAttr('aria-hidden', 'false') + describe('showHint', () => + it('show the help overlay', function() { + this.calculator.showHint(); + expect($('.help')).toHaveClass('shown'); + return expect($('.help')).toHaveAttr('aria-hidden', 'false'); + }) + ); - describe 'hideHint', -> - it 'show the help overlay', -> - @calculator.hideHint() - expect($('.help')).not.toHaveClass('shown') - expect($('.help')).toHaveAttr('aria-hidden', 'true') + describe('hideHint', () => + it('show the help overlay', function() { + this.calculator.hideHint(); + expect($('.help')).not.toHaveClass('shown'); + return expect($('.help')).toHaveAttr('aria-hidden', 'true'); + }) + ); - describe 'handleClickOnHintButton', -> - it 'on click hint button hint popup becomes visible ', -> - e = jQuery.Event('click'); + describe('handleClickOnHintButton', () => + it('on click hint button hint popup becomes visible ', function() { + const e = jQuery.Event('click'); $('#calculator_hint').trigger(e); - expect($('.help')).toHaveClass 'shown' + return expect($('.help')).toHaveClass('shown'); + }) + ); - describe 'handleClickOnDocument', -> - it 'on click out of the hint popup it becomes hidden', -> - @calculator.showHint() - e = jQuery.Event('click'); + describe('handleClickOnDocument', () => + it('on click out of the hint popup it becomes hidden', function() { + this.calculator.showHint(); + const e = jQuery.Event('click'); $(document).trigger(e); - expect($('.help')).not.toHaveClass 'shown' + return expect($('.help')).not.toHaveClass('shown'); + }) + ); - describe 'handleClickOnHintPopup', -> - it 'on click of hint popup it remains visible', -> - @calculator.showHint() - e = jQuery.Event('click'); + describe('handleClickOnHintPopup', () => + it('on click of hint popup it remains visible', function() { + this.calculator.showHint(); + const e = jQuery.Event('click'); $('#calculator_input_help').trigger(e); - expect($('.help')).toHaveClass 'shown' + return expect($('.help')).toHaveClass('shown'); + }) + ); - describe 'selectHint', -> - it 'select correct hint item', -> - spyOn($.fn, 'focus') - element = $('.hint-item').eq(1) - @calculator.selectHint(element) + describe('selectHint', function() { + it('select correct hint item', function() { + spyOn($.fn, 'focus'); + const element = $('.hint-item').eq(1); + this.calculator.selectHint(element); - expect(element.focus).toHaveBeenCalled() - expect(@calculator.activeHint).toEqual(element) - expect(@calculator.hintPopup).toHaveAttr('data-calculator-hint', element.attr('id')) + expect(element.focus).toHaveBeenCalled(); + expect(this.calculator.activeHint).toEqual(element); + return expect(this.calculator.hintPopup).toHaveAttr('data-calculator-hint', element.attr('id')); + }); - it 'select the first hint if argument element is not passed', -> - @calculator.selectHint() - expect(@calculator.activeHint.attr('id')).toEqual($('.hint-item').first().attr('id')) + it('select the first hint if argument element is not passed', function() { + this.calculator.selectHint(); + return expect(this.calculator.activeHint.attr('id')).toEqual($('.hint-item').first().attr('id')); + }); - it 'select the first hint if argument element is empty', -> - @calculator.selectHint([]) - expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').first().attr('id')) + return it('select the first hint if argument element is empty', function() { + this.calculator.selectHint([]); + return expect(this.calculator.activeHint.attr('id')).toBe($('.hint-item').first().attr('id')); + }); + }); - describe 'prevHint', -> + describe('prevHint', function() { - it 'Prev hint item is selected', -> - @calculator.activeHint = $('.hint-item').eq(1) - @calculator.prevHint() + it('Prev hint item is selected', function() { + this.calculator.activeHint = $('.hint-item').eq(1); + this.calculator.prevHint(); - expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id')) + return expect(this.calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id')); + }); - it 'if this was the second item, select the first one', -> - @calculator.activeHint = $('.hint-item').eq(1) - @calculator.prevHint() + it('if this was the second item, select the first one', function() { + this.calculator.activeHint = $('.hint-item').eq(1); + this.calculator.prevHint(); - expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id')) + return expect(this.calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id')); + }); - it 'if this was the first item, select the last one', -> - @calculator.activeHint = $('.hint-item').eq(0) - @calculator.prevHint() + it('if this was the first item, select the last one', function() { + this.calculator.activeHint = $('.hint-item').eq(0); + this.calculator.prevHint(); - expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(2).attr('id')) + return expect(this.calculator.activeHint.attr('id')).toBe($('.hint-item').eq(2).attr('id')); + }); - it 'if this was the last item, select the second last', -> - @calculator.activeHint = $('.hint-item').eq(2) - @calculator.prevHint() + return it('if this was the last item, select the second last', function() { + this.calculator.activeHint = $('.hint-item').eq(2); + this.calculator.prevHint(); - expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(1).attr('id')) + return expect(this.calculator.activeHint.attr('id')).toBe($('.hint-item').eq(1).attr('id')); + }); + }); - describe 'nextHint', -> + describe('nextHint', function() { - it 'if this was the first item, select the second one', -> - @calculator.activeHint = $('.hint-item').eq(0) - @calculator.nextHint() + it('if this was the first item, select the second one', function() { + this.calculator.activeHint = $('.hint-item').eq(0); + this.calculator.nextHint(); - expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(1).attr('id')) + return expect(this.calculator.activeHint.attr('id')).toBe($('.hint-item').eq(1).attr('id')); + }); - it 'If this was the second item, select the last one', -> - @calculator.activeHint = $('.hint-item').eq(1) - @calculator.nextHint() + it('If this was the second item, select the last one', function() { + this.calculator.activeHint = $('.hint-item').eq(1); + this.calculator.nextHint(); - expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(2).attr('id')) + return expect(this.calculator.activeHint.attr('id')).toBe($('.hint-item').eq(2).attr('id')); + }); - it 'If this was the last item, select the first one', -> - @calculator.activeHint = $('.hint-item').eq(2) - @calculator.nextHint() + return it('If this was the last item, select the first one', function() { + this.calculator.activeHint = $('.hint-item').eq(2); + this.calculator.nextHint(); - expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id')) + return expect(this.calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id')); + }); + }); - describe 'handleKeyDown', -> - assertHintIsHidden = (calc, key) -> - spyOn(calc, 'hideHint') - calc.showHint() - e = jQuery.Event('keydown', { keyCode: key }); - value = calc.handleKeyDown(e) + describe('handleKeyDown', function() { + const assertHintIsHidden = function(calc, key) { + spyOn(calc, 'hideHint'); + calc.showHint(); + const e = jQuery.Event('keydown', { keyCode: key }); + const value = calc.handleKeyDown(e); - expect(calc.hideHint).toHaveBeenCalled - expect(value).toBeFalsy() - expect(e.isDefaultPrevented()).toBeTruthy() + expect(calc.hideHint).toHaveBeenCalled; + expect(value).toBeFalsy(); + return expect(e.isDefaultPrevented()).toBeTruthy(); + }; - assertHintIsVisible = (calc, key) -> - spyOn(calc, 'showHint') - spyOn($.fn, 'focus') - e = jQuery.Event('keydown', { keyCode: key }); - value = calc.handleKeyDown(e) + const assertHintIsVisible = function(calc, key) { + spyOn(calc, 'showHint'); + spyOn($.fn, 'focus'); + const e = jQuery.Event('keydown', { keyCode: key }); + const value = calc.handleKeyDown(e); - expect(calc.showHint).toHaveBeenCalled - expect(value).toBeFalsy() - expect(e.isDefaultPrevented()).toBeTruthy() - expect(calc.activeHint.focus).toHaveBeenCalled() + expect(calc.showHint).toHaveBeenCalled; + expect(value).toBeFalsy(); + expect(e.isDefaultPrevented()).toBeTruthy(); + return expect(calc.activeHint.focus).toHaveBeenCalled(); + }; - assertNothingHappens = (calc, key) -> - spyOn(calc, 'showHint') - e = jQuery.Event('keydown', { keyCode: key }); - value = calc.handleKeyDown(e) + const assertNothingHappens = function(calc, key) { + spyOn(calc, 'showHint'); + const e = jQuery.Event('keydown', { keyCode: key }); + const value = calc.handleKeyDown(e); - expect(calc.showHint).not.toHaveBeenCalled - expect(value).toBeTruthy() - expect(e.isDefaultPrevented()).toBeFalsy() + expect(calc.showHint).not.toHaveBeenCalled; + expect(value).toBeTruthy(); + return expect(e.isDefaultPrevented()).toBeFalsy(); + }; - it 'hint popup becomes hidden on press ENTER', -> - assertHintIsHidden(@calculator, KEY.ENTER) + it('hint popup becomes hidden on press ENTER', function() { + return assertHintIsHidden(this.calculator, KEY.ENTER); + }); - it 'hint popup becomes visible on press ENTER', -> - assertHintIsVisible(@calculator, KEY.ENTER) + it('hint popup becomes visible on press ENTER', function() { + return assertHintIsVisible(this.calculator, KEY.ENTER); + }); - it 'hint popup becomes hidden on press SPACE', -> - assertHintIsHidden(@calculator, KEY.SPACE) + it('hint popup becomes hidden on press SPACE', function() { + return assertHintIsHidden(this.calculator, KEY.SPACE); + }); - it 'hint popup becomes visible on press SPACE', -> - assertHintIsVisible(@calculator, KEY.SPACE) + it('hint popup becomes visible on press SPACE', function() { + return assertHintIsVisible(this.calculator, KEY.SPACE); + }); - it 'Nothing happens on press ALT', -> - assertNothingHappens(@calculator, KEY.ALT) + it('Nothing happens on press ALT', function() { + return assertNothingHappens(this.calculator, KEY.ALT); + }); - it 'Nothing happens on press any other button', -> - assertNothingHappens(@calculator, KEY.DOWN) + return it('Nothing happens on press any other button', function() { + return assertNothingHappens(this.calculator, KEY.DOWN); + }); + }); - describe 'handleKeyDownOnHint', -> - it 'Navigation works in proper way', -> - calc = @calculator + describe('handleKeyDownOnHint', () => + it('Navigation works in proper way', function() { + const calc = this.calculator; - eventToShowHint = jQuery.Event('keydown', { keyCode: KEY.ENTER } ); + const eventToShowHint = jQuery.Event('keydown', { keyCode: KEY.ENTER } ); $('#calculator_hint').trigger(eventToShowHint); - spyOn(calc, 'hideHint') - spyOn(calc, 'prevHint') - spyOn(calc, 'nextHint') - spyOn($.fn, 'focus') + spyOn(calc, 'hideHint'); + spyOn(calc, 'prevHint'); + spyOn(calc, 'nextHint'); + spyOn($.fn, 'focus'); - cases = - left: - event: - keyCode: KEY.LEFT + const cases = { + left: { + event: { + keyCode: KEY.LEFT, shiftKey: false - returnedValue: false - called: + }, + returnedValue: false, + called: { 'prevHint': calc + }, isPropagationStopped: true + }, - leftWithShift: - returnedValue: true - event: - keyCode: KEY.LEFT + leftWithShift: { + returnedValue: true, + event: { + keyCode: KEY.LEFT, shiftKey: true - not_called: + }, + not_called: { 'prevHint': calc + } + }, - up: - event: - keyCode: KEY.UP + up: { + event: { + keyCode: KEY.UP, shiftKey: false - returnedValue: false - called: + }, + returnedValue: false, + called: { 'prevHint': calc + }, isPropagationStopped: true + }, - upWithShift: - returnedValue: true - event: - keyCode: KEY.UP + upWithShift: { + returnedValue: true, + event: { + keyCode: KEY.UP, shiftKey: true - not_called: + }, + not_called: { 'prevHint': calc + } + }, - right: - event: - keyCode: KEY.RIGHT + right: { + event: { + keyCode: KEY.RIGHT, shiftKey: false - returnedValue: false - called: + }, + returnedValue: false, + called: { 'nextHint': calc + }, isPropagationStopped: true + }, - rightWithShift: - returnedValue: true - event: - keyCode: KEY.RIGHT + rightWithShift: { + returnedValue: true, + event: { + keyCode: KEY.RIGHT, shiftKey: true - not_called: + }, + not_called: { 'nextHint': calc + } + }, - down: - event: - keyCode: KEY.DOWN + down: { + event: { + keyCode: KEY.DOWN, shiftKey: false - returnedValue: false - called: + }, + returnedValue: false, + called: { 'nextHint': calc + }, isPropagationStopped: true + }, - downWithShift: - returnedValue: true - event: - keyCode: KEY.DOWN + downWithShift: { + returnedValue: true, + event: { + keyCode: KEY.DOWN, shiftKey: true - not_called: + }, + not_called: { 'nextHint': calc + } + }, - esc: - returnedValue: false - event: - keyCode: KEY.ESC + esc: { + returnedValue: false, + event: { + keyCode: KEY.ESC, shiftKey: false - called: - 'hideHint': calc + }, + called: { + 'hideHint': calc, 'focus': $.fn + }, isPropagationStopped: true + }, - alt: - returnedValue: true - event: + alt: { + returnedValue: true, + event: { which: KEY.ALT - not_called: - 'hideHint': calc - 'nextHint': calc + }, + not_called: { + 'hideHint': calc, + 'nextHint': calc, 'prevHint': calc + } + } + }; - $.each(cases, (key, data) -> - calc.hideHint.calls.reset() - calc.prevHint.calls.reset() - calc.nextHint.calls.reset() - $.fn.focus.calls.reset() + return $.each(cases, function(key, data) { + calc.hideHint.calls.reset(); + calc.prevHint.calls.reset(); + calc.nextHint.calls.reset(); + $.fn.focus.calls.reset(); - e = jQuery.Event('keydown', data.event or {}); - value = calc.handleKeyDownOnHint(e) + const e = jQuery.Event('keydown', data.event || {}); + const value = calc.handleKeyDownOnHint(e); - if data.called - $.each(data.called, (method, obj) -> - expect(obj[method]).toHaveBeenCalled() - ) + if (data.called) { + $.each(data.called, (method, obj) => expect(obj[method]).toHaveBeenCalled()); + } - if data.not_called - $.each(data.not_called, (method, obj) -> - expect(obj[method]).not.toHaveBeenCalled() - ) + if (data.not_called) { + $.each(data.not_called, (method, obj) => expect(obj[method]).not.toHaveBeenCalled()); + } - if data.isPropagationStopped - expect(e.isPropagationStopped()).toBeTruthy() - else - expect(e.isPropagationStopped()).toBeFalsy() + if (data.isPropagationStopped) { + expect(e.isPropagationStopped()).toBeTruthy(); + } else { + expect(e.isPropagationStopped()).toBeFalsy(); + } - expect(value).toBe(data.returnedValue) - ) + return expect(value).toBe(data.returnedValue); + }); + }) + ); - describe 'calculate', -> - beforeEach -> - $('#calculator_input').val '1+2' - spyOn($, 'getWithPrefix').and.callFake (url, data, callback) -> - callback({ result: 3 }) - @calculator.calculate() + return describe('calculate', function() { + beforeEach(function() { + $('#calculator_input').val('1+2'); + spyOn($, 'getWithPrefix').and.callFake((url, data, callback) => callback({ result: 3 })); + return this.calculator.calculate(); + }); - it 'send data to /calculate', -> - expect($.getWithPrefix).toHaveBeenCalledWith '/calculate', - equation: '1+2' - , jasmine.any(Function) + it('send data to /calculate', () => + expect($.getWithPrefix).toHaveBeenCalledWith('/calculate', + {equation: '1+2'} + , jasmine.any(Function)) + ); - it 'update the calculator output', -> - expect($('#calculator_output').val()).toEqual('3') + return it('update the calculator output', () => expect($('#calculator_output').val()).toEqual('3')); + }); +}); diff --git a/lms/static/coffee/spec/courseware_spec.js b/lms/static/coffee/spec/courseware_spec.js index 129b4308a6..3be0cda49c 100644 --- a/lms/static/coffee/spec/courseware_spec.js +++ b/lms/static/coffee/spec/courseware_spec.js @@ -1,31 +1,40 @@ -describe 'Courseware', -> - describe 'start', -> - it 'binds the Logger', -> - spyOn(Logger, 'bind') - Courseware.start() - expect(Logger.bind).toHaveBeenCalled() +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +describe('Courseware', function() { + describe('start', () => + it('binds the Logger', function() { + spyOn(Logger, 'bind'); + Courseware.start(); + return expect(Logger.bind).toHaveBeenCalled(); + }) + ); - describe 'render', -> - beforeEach -> - jasmine.stubRequests() - @courseware = new Courseware - spyOn(window, 'Histogram') - spyOn(window, 'Problem') - spyOn(window, 'Video') - spyOn(XBlock, 'initializeBlocks') - setFixtures """ -
-
-
-
-
-
-
- """ - @courseware.render() + return describe('render', function() { + beforeEach(function() { + jasmine.stubRequests(); + this.courseware = new Courseware; + spyOn(window, 'Histogram'); + spyOn(window, 'Problem'); + spyOn(window, 'Video'); + spyOn(XBlock, 'initializeBlocks'); + setFixtures(`\ +
+
+
+
+
+
+
\ +` + ); + return this.courseware.render(); + }); - it 'ensure that the XModules have been loaded', -> - expect(XBlock.initializeBlocks).toHaveBeenCalled() + it('ensure that the XModules have been loaded', () => expect(XBlock.initializeBlocks).toHaveBeenCalled()); - it 'detect the histrogram element and convert it', -> - expect(window.Histogram).toHaveBeenCalledWith('3', [[0, 1]]) + return it('detect the histrogram element and convert it', () => expect(window.Histogram).toHaveBeenCalledWith('3', [[0, 1]])); + }); +}); diff --git a/lms/static/coffee/spec/feedback_form_spec.js b/lms/static/coffee/spec/feedback_form_spec.js index c821ee5153..4bb1db685c 100644 --- a/lms/static/coffee/spec/feedback_form_spec.js +++ b/lms/static/coffee/spec/feedback_form_spec.js @@ -1,25 +1,33 @@ -describe 'FeedbackForm', -> - beforeEach -> - loadFixtures 'coffee/fixtures/feedback_form.html' +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +describe('FeedbackForm', function() { + beforeEach(() => loadFixtures('coffee/fixtures/feedback_form.html')); - describe 'constructor', -> - beforeEach -> - new FeedbackForm - spyOn($, 'postWithPrefix').and.callFake (url, data, callback, format) -> - callback() + return describe('constructor', function() { + beforeEach(function() { + new FeedbackForm; + return spyOn($, 'postWithPrefix').and.callFake((url, data, callback, format) => callback()); + }); - it 'post data to /send_feedback on click', -> - $('#feedback_subject').val 'Awesome!' - $('#feedback_message').val 'This site is really good.' - $('#feedback_button').click() + it('post data to /send_feedback on click', function() { + $('#feedback_subject').val('Awesome!'); + $('#feedback_message').val('This site is really good.'); + $('#feedback_button').click(); - expect($.postWithPrefix).toHaveBeenCalledWith '/send_feedback', { - subject: 'Awesome!' - message: 'This site is really good.' + return expect($.postWithPrefix).toHaveBeenCalledWith('/send_feedback', { + subject: 'Awesome!', + message: 'This site is really good.', url: window.location.href - }, jasmine.any(Function), 'json' + }, jasmine.any(Function), 'json'); + }); - it 'replace the form with a thank you message', -> - $('#feedback_button').click() + return it('replace the form with a thank you message', function() { + $('#feedback_button').click(); - expect($('#feedback_div').html()).toEqual 'Feedback submitted. Thank you' + return expect($('#feedback_div').html()).toEqual('Feedback submitted. Thank you'); + }); + }); +}); diff --git a/lms/static/coffee/spec/helper.js b/lms/static/coffee/spec/helper.js index 0595362cec..b66ece165c 100644 --- a/lms/static/coffee/spec/helper.js +++ b/lms/static/coffee/spec/helper.js @@ -1,72 +1,96 @@ -jasmine.stubbedMetadata = - slowerSpeedYoutubeId: - id: 'slowerSpeedYoutubeId' +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +jasmine.stubbedMetadata = { + slowerSpeedYoutubeId: { + id: 'slowerSpeedYoutubeId', duration: 300 - normalSpeedYoutubeId: - id: 'normalSpeedYoutubeId' + }, + normalSpeedYoutubeId: { + id: 'normalSpeedYoutubeId', duration: 200 - bogus: + }, + bogus: { duration: 100 + } +}; -jasmine.stubbedCaption = - start: [0, 10000, 20000, 30000] +jasmine.stubbedCaption = { + start: [0, 10000, 20000, 30000], text: ['Caption at 0', 'Caption at 10000', 'Caption at 20000', 'Caption at 30000'] +}; -jasmine.stubRequests = -> - spyOn($, 'ajax').and.callFake (settings) -> - if match = settings.url.match /youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/ - settings.success data: jasmine.stubbedMetadata[match[1]] - else if match = settings.url.match /static\/subs\/(.+)\.srt\.sjson/ - settings.success jasmine.stubbedCaption - else if settings.url.match /modx\/.+\/problem_get$/ - settings.success html: readFixtures('problem_content.html') - else if settings.url == '/calculate' || +jasmine.stubRequests = () => + spyOn($, 'ajax').and.callFake(function(settings) { + let match; + if (match = settings.url.match(/youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/)) { + return settings.success({data: jasmine.stubbedMetadata[match[1]]}); + } else if (match = settings.url.match(/static\/subs\/(.+)\.srt\.sjson/)) { + return settings.success(jasmine.stubbedCaption); + } else if (settings.url.match(/modx\/.+\/problem_get$/)) { + return settings.success({html: readFixtures('problem_content.html')}); + } else if ((settings.url === '/calculate') || settings.url.match(/modx\/.+\/goto_position$/) || settings.url.match(/event$/) || - settings.url.match(/modx\/.+\/problem_(check|reset|show|save)$/) - # do nothing - else - throw "External request attempted for #{settings.url}, which is not defined." + settings.url.match(/modx\/.+\/problem_(check|reset|show|save)$/)) { + // do nothing + } else { + throw `External request attempted for ${settings.url}, which is not defined.`; + } + }) +; -jasmine.stubYoutubePlayer = -> - YT.Player = -> jasmine.createSpyObj 'YT.Player', ['cueVideoById', 'getVideoEmbedCode', +jasmine.stubYoutubePlayer = () => + YT.Player = () => jasmine.createSpyObj('YT.Player', ['cueVideoById', 'getVideoEmbedCode', 'getCurrentTime', 'getPlayerState', 'getVolume', 'setVolume', 'loadVideoById', - 'playVideo', 'pauseVideo', 'seekTo'] + 'playVideo', 'pauseVideo', 'seekTo']) +; -jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) -> - enableParts = [enableParts] unless $.isArray(enableParts) +jasmine.stubVideoPlayer = function(context, enableParts, createPlayer) { + let currentPartName; + if (createPlayer == null) { createPlayer = true; } + if (!$.isArray(enableParts)) { enableParts = [enableParts]; } - suite = context.suite - currentPartName = suite.description while suite = suite.parentSuite - enableParts.push currentPartName + let { suite } = context; + while ((suite = suite.parentSuite)) { currentPartName = suite.description; } + enableParts.push(currentPartName); - for part in ['VideoCaption', 'VideoSpeedControl', 'VideoVolumeControl', 'VideoProgressSlider'] - unless $.inArray(part, enableParts) >= 0 - spyOn window, part + for (let part of ['VideoCaption', 'VideoSpeedControl', 'VideoVolumeControl', 'VideoProgressSlider']) { + if (!($.inArray(part, enableParts) >= 0)) { + spyOn(window, part); + } + } - loadFixtures 'video.html' - jasmine.stubRequests() - YT.Player = undefined - context.video = new Video 'example', '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId' - jasmine.stubYoutubePlayer() - if createPlayer - return new VideoPlayer(video: context.video) + loadFixtures('video.html'); + jasmine.stubRequests(); + YT.Player = undefined; + context.video = new Video('example', '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId'); + jasmine.stubYoutubePlayer(); + if (createPlayer) { + return new VideoPlayer({video: context.video}); + } +}; -# Stub Youtube API -window.YT = - PlayerState: - UNSTARTED: -1 - ENDED: 0 - PLAYING: 1 - PAUSED: 2 - BUFFERING: 3 +// Stub Youtube API +window.YT = { + PlayerState: { + UNSTARTED: -1, + ENDED: 0, + PLAYING: 1, + PAUSED: 2, + BUFFERING: 3, CUED: 5 + } +}; -# Stub jQuery.cookie -$.cookie = jasmine.createSpy('jQuery.cookie').and.returnValue '1.0' +// Stub jQuery.cookie +$.cookie = jasmine.createSpy('jQuery.cookie').and.returnValue('1.0'); -# Stub jQuery.qtip -$.fn.qtip = jasmine.createSpy 'jQuery.qtip' +// Stub jQuery.qtip +$.fn.qtip = jasmine.createSpy('jQuery.qtip'); -# Stub jQuery.scrollTo -$.fn.scrollTo = jasmine.createSpy 'jQuery.scrollTo' +// Stub jQuery.scrollTo +$.fn.scrollTo = jasmine.createSpy('jQuery.scrollTo'); diff --git a/lms/static/coffee/spec/histogram_spec.js b/lms/static/coffee/spec/histogram_spec.js index 9616b37223..0acec71b59 100644 --- a/lms/static/coffee/spec/histogram_spec.js +++ b/lms/static/coffee/spec/histogram_spec.js @@ -1,54 +1,72 @@ -describe 'Histogram', -> - beforeEach -> - spyOn $, 'plot' +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +describe('Histogram', function() { + beforeEach(() => spyOn($, 'plot')); - describe 'constructor', -> - it 'instantiate the data arrays', -> - histogram = new Histogram 1, [] - expect(histogram.xTicks).toEqual [] - expect(histogram.yTicks).toEqual [] - expect(histogram.data).toEqual [] + describe('constructor', () => + it('instantiate the data arrays', function() { + const histogram = new Histogram(1, []); + expect(histogram.xTicks).toEqual([]); + expect(histogram.yTicks).toEqual([]); + return expect(histogram.data).toEqual([]); + }) +); - describe 'calculate', -> - beforeEach -> - @histogram = new Histogram(1, [[null, 1], [1, 1], [2, 2], [3, 3]]) + describe('calculate', function() { + beforeEach(function() { + return this.histogram = new Histogram(1, [[null, 1], [1, 1], [2, 2], [3, 3]]); + }); - it 'store the correct value for data', -> - expect(@histogram.data).toEqual [[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]] + it('store the correct value for data', function() { + return expect(this.histogram.data).toEqual([[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]]); + }); - it 'store the correct value for x ticks', -> - expect(@histogram.xTicks).toEqual [[1, '1'], [2, '2'], [3, '3']] + it('store the correct value for x ticks', function() { + return expect(this.histogram.xTicks).toEqual([[1, '1'], [2, '2'], [3, '3']]); + }); - it 'store the correct value for y ticks', -> - expect(@histogram.yTicks).toEqual + return it('store the correct value for y ticks', function() { + return expect(this.histogram.yTicks).toEqual; + }); + }); - describe 'render', -> - it 'call flot with correct option', -> - new Histogram(1, [[1, 1], [2, 2], [3, 3]]) + return describe('render', () => + it('call flot with correct option', function() { + new Histogram(1, [[1, 1], [2, 2], [3, 3]]); - firstArg = $.plot.calls.mostRecent().args[0] - secondArg = $.plot.calls.mostRecent().args[1] - thirdArg = $.plot.calls.mostRecent().args[2] + const firstArg = $.plot.calls.mostRecent().args[0]; + const secondArg = $.plot.calls.mostRecent().args[1]; + const thirdArg = $.plot.calls.mostRecent().args[2]; - expect(firstArg.selector).toEqual($("#histogram_1").selector) - expect(secondArg).toEqual([ - data: [[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]] - bars: - show: true - align: 'center' - lineWidth: 0 + expect(firstArg.selector).toEqual($("#histogram_1").selector); + expect(secondArg).toEqual([{ + data: [[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]], + bars: { + show: true, + align: 'center', + lineWidth: 0, fill: 1.0 + }, color: "#b72121" - ]) - expect(thirdArg).toEqual( - xaxis: - min: -1 - max: 4 - ticks: [[1, '1'], [2, '2'], [3, '3']] + } + ]); + return expect(thirdArg).toEqual({ + xaxis: { + min: -1, + max: 4, + ticks: [[1, '1'], [2, '2'], [3, '3']], tickLength: 0 - yaxis: - min: 0.0 - max: Math.log(4) * 1.1 - ticks: [[Math.log(2), '1'], [Math.log(3), '2'], [Math.log(4), '3']] + }, + yaxis: { + min: 0.0, + max: Math.log(4) * 1.1, + ticks: [[Math.log(2), '1'], [Math.log(3), '2'], [Math.log(4), '3']], labelWidth: 50 - ) + } + }); + }) + ); +}); diff --git a/lms/static/coffee/spec/modules/tab_spec.js b/lms/static/coffee/spec/modules/tab_spec.js index a664cb1017..56751669ac 100644 --- a/lms/static/coffee/spec/modules/tab_spec.js +++ b/lms/static/coffee/spec/modules/tab_spec.js @@ -1,44 +1,61 @@ -describe 'Tab', -> - beforeEach -> - loadFixtures 'coffee/fixtures/tab.html' - @items = $.parseJSON readFixtures('coffee/fixtures/items.json') +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +describe('Tab', function() { + beforeEach(function() { + loadFixtures('coffee/fixtures/tab.html'); + return this.items = $.parseJSON(readFixtures('coffee/fixtures/items.json')); + }); - describe 'constructor', -> - beforeEach -> - spyOn($.fn, 'tabs') - @tab = new Tab 1, @items + describe('constructor', function() { + beforeEach(function() { + spyOn($.fn, 'tabs'); + return this.tab = new Tab(1, this.items); + }); - it 'set the element', -> - expect(@tab.el).toEqual $('#tab_1') + it('set the element', function() { + return expect(this.tab.el).toEqual($('#tab_1')); + }); - it 'build the tabs', -> - links = $('.navigation li>a').map(-> $(this).attr('href')).get() - expect(links).toEqual ['#tab-1-0', '#tab-1-1', '#tab-1-2'] + it('build the tabs', function() { + const links = $('.navigation li>a').map(function() { return $(this).attr('href'); }).get(); + return expect(links).toEqual(['#tab-1-0', '#tab-1-1', '#tab-1-2']); + }); - it 'build the container', -> - containers = $('section').map(-> $(this).attr('id')).get() - expect(containers).toEqual ['tab-1-0', 'tab-1-1', 'tab-1-2'] + it('build the container', function() { + const containers = $('section').map(function() { return $(this).attr('id'); }).get(); + return expect(containers).toEqual(['tab-1-0', 'tab-1-1', 'tab-1-2']); + }); - it 'bind the tabs', -> - expect($.fn.tabs).toHaveBeenCalledWith show: @tab.onShow + return it('bind the tabs', function() { + return expect($.fn.tabs).toHaveBeenCalledWith({show: this.tab.onShow}); + }); + }); - # As of jQuery 1.9, the onShow callback is deprecated - # http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate - # The code below tests that onShow does what is expected, - # but note that onShow will NOT be called when the user - # clicks on the tab if we're using jQuery version >= 1.9 - describe 'onShow', -> - beforeEach -> - @tab = new Tab 1, @items - @tab.onShow($('#tab-1-0'), {'index': 1}) + // As of jQuery 1.9, the onShow callback is deprecated + // http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate + // The code below tests that onShow does what is expected, + // but note that onShow will NOT be called when the user + // clicks on the tab if we're using jQuery version >= 1.9 + return describe('onShow', function() { + beforeEach(function() { + this.tab = new Tab(1, this.items); + return this.tab.onShow($('#tab-1-0'), {'index': 1}); + }); - it 'replace content in the container', -> - @tab.onShow($('#tab-1-1'), {'index': 1}) - expect($('#tab-1-0').html()).toEqual '' - expect($('#tab-1-1').html()).toEqual 'Video 2' - expect($('#tab-1-2').html()).toEqual '' + it('replace content in the container', function() { + this.tab.onShow($('#tab-1-1'), {'index': 1}); + expect($('#tab-1-0').html()).toEqual(''); + expect($('#tab-1-1').html()).toEqual('Video 2'); + return expect($('#tab-1-2').html()).toEqual(''); + }); - it 'trigger contentChanged event on the element', -> - spyOnEvent @tab.el, 'contentChanged' - @tab.onShow($('#tab-1-1'), {'index': 1}) - expect('contentChanged').toHaveBeenTriggeredOn @tab.el + return it('trigger contentChanged event on the element', function() { + spyOnEvent(this.tab.el, 'contentChanged'); + this.tab.onShow($('#tab-1-1'), {'index': 1}); + return expect('contentChanged').toHaveBeenTriggeredOn(this.tab.el); + }); + }); +}); diff --git a/lms/static/coffee/spec/requirejs_spec.js b/lms/static/coffee/spec/requirejs_spec.js index 369904f683..c5829b81f5 100644 --- a/lms/static/coffee/spec/requirejs_spec.js +++ b/lms/static/coffee/spec/requirejs_spec.js @@ -1,95 +1,114 @@ -describe "RequireJS namespacing", -> - beforeEach -> +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +describe("RequireJS namespacing", function() { + beforeEach(() => - # Jasmine does not provide a way to use the typeof operator. We need - # to create our own custom matchers so that a TypeError is not thrown. - jasmine.addMatchers - requirejsTobeUndefined: -> - { - compare: -> - { - pass: typeof requirejs is "undefined" - } + // Jasmine does not provide a way to use the typeof operator. We need + // to create our own custom matchers so that a TypeError is not thrown. + jasmine.addMatchers({ + requirejsTobeUndefined() { + return { + compare() { + return { + pass: typeof requirejs === "undefined" + }; } + }; + }, - requireTobeUndefined: -> - { - compare: -> - { - pass: typeof require is "undefined" - } + requireTobeUndefined() { + return { + compare() { + return { + pass: typeof require === "undefined" + }; } + }; + }, - defineTobeUndefined: -> - { - compare: -> - { - pass: typeof define is "undefined" - } + defineTobeUndefined() { + return { + compare() { + return { + pass: typeof define === "undefined" + }; } + }; + }})); - it "check that the RequireJS object is present in the global namespace", -> - expect(RequireJS).toEqual jasmine.any(Object) - expect(window.RequireJS).toEqual jasmine.any(Object) + it("check that the RequireJS object is present in the global namespace", function() { + expect(RequireJS).toEqual(jasmine.any(Object)); + return expect(window.RequireJS).toEqual(jasmine.any(Object)); + }); - it "check that requirejs(), require(), and define() are not in the global namespace", -> + return it("check that requirejs(), require(), and define() are not in the global namespace", function() { - # The custom matchers that we defined in the beforeEach() function do - # not operate on an object. We pass a dummy empty object {} not to - # confuse Jasmine. - expect({}).requirejsTobeUndefined() - expect({}).requireTobeUndefined() - expect({}).defineTobeUndefined() - expect(window.requirejs).not.toBeDefined() - expect(window.require).not.toBeDefined() - expect(window.define).not.toBeDefined() + // The custom matchers that we defined in the beforeEach() function do + // not operate on an object. We pass a dummy empty object {} not to + // confuse Jasmine. + expect({}).requirejsTobeUndefined(); + expect({}).requireTobeUndefined(); + expect({}).defineTobeUndefined(); + expect(window.requirejs).not.toBeDefined(); + expect(window.require).not.toBeDefined(); + return expect(window.define).not.toBeDefined(); + }); +}); -describe "RequireJS module creation", -> - inDefineCallback = undefined - inRequireCallback = undefined - it "check that we can use RequireJS to define() and require() a module", (done) -> - d1 = $.Deferred() - d2 = $.Deferred() - # Because Require JS works asynchronously when defining and requiring - # modules, we need to use the special Jasmine functions runs(), and - # waitsFor() to set up this test. - func = () -> +describe("RequireJS module creation", function() { + let inDefineCallback = undefined; + let inRequireCallback = undefined; + return it("check that we can use RequireJS to define() and require() a module", function(done) { + const d1 = $.Deferred(); + const d2 = $.Deferred(); + // Because Require JS works asynchronously when defining and requiring + // modules, we need to use the special Jasmine functions runs(), and + // waitsFor() to set up this test. + const func = function() { - # Initialize the variable that we will test for. They will be set - # to true in the appropriate callback functions called by Require - # JS. If their values do not change, this will mean that something - # is not working as is intended. - inDefineCallback = false - inRequireCallback = false + // Initialize the variable that we will test for. They will be set + // to true in the appropriate callback functions called by Require + // JS. If their values do not change, this will mean that something + // is not working as is intended. + inDefineCallback = false; + inRequireCallback = false; - # Define our test module. - RequireJS.define "test_module", [], -> - inDefineCallback = true + // Define our test module. + RequireJS.define("test_module", [], function() { + inDefineCallback = true; - d1.resolve() + d1.resolve(); - # This module returns an object. It can be accessed via the - # Require JS require() function. - module_status: "OK" + // This module returns an object. It can be accessed via the + // Require JS require() function. + return {module_status: "OK"}; + }); - # Require our defined test module. - RequireJS.require ["test_module"], (test_module) -> - inRequireCallback = true + // Require our defined test module. + return RequireJS.require(["test_module"], function(test_module) { + inRequireCallback = true; - # If our test module was defined properly, then we should - # be able to get the object it returned, and query some - # property. - expect(test_module.module_status).toBe "OK" + // If our test module was defined properly, then we should + // be able to get the object it returned, and query some + // property. + expect(test_module.module_status).toBe("OK"); - d2.resolve() + return d2.resolve(); + }); + }; - func() - # We will wait before checking if our module was defined and that we were able to require() the module. - $.when(d1, d2).done(-> - # The final test behavior - expect(inDefineCallback).toBeTruthy() - expect(inRequireCallback).toBeTruthy() - ).always(done) + func(); + // We will wait before checking if our module was defined and that we were able to require() the module. + return $.when(d1, d2).done(function() { + // The final test behavior + expect(inDefineCallback).toBeTruthy(); + return expect(inRequireCallback).toBeTruthy(); + }).always(done); + }); +});