Commit 0880502f by David Ormsbee Committed by Calen Pennington

CoffeeScript tests migration: Decaffeinate files

This is running decaffeinate, with no additional cleanup.
parent 5c64da2f
define ["js/models/course"], (Course) -> /*
describe "Course", -> * decaffeinate suggestions:
describe "basic", -> * DS102: Remove unnecessary code created because of implicit returns
beforeEach -> * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
@model = new Course({ */
define(["js/models/course"], Course =>
describe("Course", () =>
describe("basic", function() {
beforeEach(function() {
return this.model = new Course({
name: "Greek Hero" name: "Greek Hero"
}) });
});
it "should take a name argument", -> return it("should take a name argument", function() {
expect(@model.get("name")).toEqual("Greek Hero") return expect(this.model.get("name")).toEqual("Greek Hero");
});
})
)
);
define ["js/models/metadata"], (Metadata) -> /*
describe "Metadata", -> * decaffeinate suggestions:
it "knows when the value has not been modified", -> * DS102: Remove unnecessary code created because of implicit returns
model = new Metadata( * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
{'value': 'original', 'explicitly_set': false}) */
expect(model.isModified()).toBeFalsy() 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( model = new Metadata(
{'value': 'original', 'explicitly_set': true}) {'value': 'original', 'explicitly_set': true});
model.setValue('original') model.setValue('original');
expect(model.isModified()).toBeFalsy() return expect(model.isModified()).toBeFalsy();
});
it "knows when the value has been modified", -> it("knows when the value has been modified", function() {
model = new Metadata( let model = new Metadata(
{'value': 'original', 'explicitly_set': false}) {'value': 'original', 'explicitly_set': false});
model.setValue('original') model.setValue('original');
expect(model.isModified()).toBeTruthy() expect(model.isModified()).toBeTruthy();
model = new Metadata( model = new Metadata(
{'value': 'original', 'explicitly_set': true}) {'value': 'original', 'explicitly_set': true});
model.setValue('modified') model.setValue('modified');
expect(model.isModified()).toBeTruthy() return expect(model.isModified()).toBeTruthy();
});
it "tracks when values have been explicitly set", -> it("tracks when values have been explicitly set", function() {
model = new Metadata( const model = new Metadata(
{'value': 'original', 'explicitly_set': false}) {'value': 'original', 'explicitly_set': false});
expect(model.isExplicitlySet()).toBeFalsy() expect(model.isExplicitlySet()).toBeFalsy();
model.setValue('original') model.setValue('original');
expect(model.isExplicitlySet()).toBeTruthy() return expect(model.isExplicitlySet()).toBeTruthy();
});
it "has both 'display value' and a 'value' methods", -> it("has both 'display value' and a 'value' methods", function() {
model = new Metadata( const model = new Metadata(
{'value': 'default', 'explicitly_set': false}) {'value': 'default', 'explicitly_set': false});
expect(model.getValue()).toBeNull expect(model.getValue()).toBeNull;
expect(model.getDisplayValue()).toBe('default') expect(model.getDisplayValue()).toBe('default');
model.setValue('modified') model.setValue('modified');
expect(model.getValue()).toBe('modified') expect(model.getValue()).toBe('modified');
expect(model.getDisplayValue()).toBe('modified') return expect(model.getDisplayValue()).toBe('modified');
});
it "has a clear method for reverting to the default", ->
model = new Metadata( it("has a clear method for reverting to the default", function() {
{'value': 'original', 'default_value' : 'default', 'explicitly_set': true}) const model = new Metadata(
model.clear() {'value': 'original', 'default_value' : 'default', 'explicitly_set': true});
expect(model.getValue()).toBeNull model.clear();
expect(model.getDisplayValue()).toBe('default') expect(model.getValue()).toBeNull;
expect(model.isExplicitlySet()).toBeFalsy() 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'});
it "has a getter for options", -> return expect(model.getFieldName()).toBe('foo');
model = new Metadata({'options': ['foo', 'bar']}) });
expect(model.getOptions()).toEqual(['foo', 'bar'])
it("has a getter for options", function() {
it "has a getter for type", -> const model = new Metadata({'options': ['foo', 'bar']});
model = new Metadata({'type': 'Integer'}) return expect(model.getOptions()).toEqual(['foo', 'bar']);
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);
});
})
);
define ["js/models/section", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers", "js/utils/module"], (Section, AjaxHelpers, ModuleUtils) -> /*
describe "Section", -> * decaffeinate suggestions:
describe "basic", -> * DS102: Remove unnecessary code created because of implicit returns
beforeEach -> * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
@model = new Section({ */
id: 42 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" name: "Life, the Universe, and Everything"
}) });
});
it "should take an id argument", -> it("should take an id argument", function() {
expect(@model.get("id")).toEqual(42) return expect(this.model.get("id")).toEqual(42);
});
it "should take a name argument", -> it("should take a name argument", function() {
expect(@model.get("name")).toEqual("Life, the Universe, and Everything") return expect(this.model.get("name")).toEqual("Life, the Universe, and Everything");
});
it "should have a URL set", -> it("should have a URL set", function() {
expect(@model.url()).toEqual(ModuleUtils.getUpdateUrl(42)) return expect(this.model.url()).toEqual(ModuleUtils.getUpdateUrl(42));
});
it "should serialize to JSON correctly", -> return it("should serialize to JSON correctly", function() {
expect(@model.toJSON()).toEqual({ return expect(this.model.toJSON()).toEqual({
metadata: metadata:
{ {
display_name: "Life, the Universe, and Everything" display_name: "Life, the Universe, and Everything"
} }
}) });
});
describe "XHR", -> });
beforeEach ->
spyOn(Section.prototype, 'showNotification') return describe("XHR", function() {
spyOn(Section.prototype, 'hideNotification') beforeEach(function() {
@model = new Section({ spyOn(Section.prototype, 'showNotification');
id: 42 spyOn(Section.prototype, 'hideNotification');
return this.model = new Section({
id: 42,
name: "Life, the Universe, and Everything" name: "Life, the Universe, and Everything"
}) });
});
it "show/hide a notification when it saves to the server", -> it("show/hide a notification when it saves to the server", function() {
server = AjaxHelpers.server([200, {"Content-Type": "application/json"}, "{}"]) const server = AjaxHelpers.server([200, {"Content-Type": "application/json"}, "{}"]);
@model.save() this.model.save();
expect(Section.prototype.showNotification).toHaveBeenCalled() expect(Section.prototype.showNotification).toHaveBeenCalled();
server.respond() server.respond();
expect(Section.prototype.hideNotification).toHaveBeenCalled() return expect(Section.prototype.hideNotification).toHaveBeenCalled();
});
it "don't hide notification when saving fails", -> return it("don't hide notification when saving fails", function() {
# this is handled by the global AJAX error handler // this is handled by the global AJAX error handler
server = AjaxHelpers.server([500, {"Content-Type": "application/json"}, "{}"]) const server = AjaxHelpers.server([500, {"Content-Type": "application/json"}, "{}"]);
@model.save() this.model.save();
server.respond() server.respond();
expect(Section.prototype.hideNotification).not.toHaveBeenCalled() return expect(Section.prototype.hideNotification).not.toHaveBeenCalled();
});
});
})
);
define ["js/models/settings/course_grader"], (CourseGrader) -> /*
describe "CourseGraderModel", -> * decaffeinate suggestions:
describe "parseWeight", -> * DS102: Remove unnecessary code created because of implicit returns
it "converts a float to an integer", -> * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
model = new CourseGrader({weight: 7.0001, min_count: 3.67, drop_count: 1.88}, {parse:true}) */
expect(model.get('weight')).toBe(7) define(["js/models/settings/course_grader"], CourseGrader =>
expect(model.get('min_count')).toBe(4) describe("CourseGraderModel", () =>
expect(model.get('drop_count')).toBe(2) 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", -> it("converts float value of weight to an integer with rounding", function() {
model = new CourseGrader({weight: 28.999999999999996}, {parse:true}) const model = new CourseGrader({weight: 28.999999999999996}, {parse:true});
expect(model.get('weight')).toBe(29) return expect(model.get('weight')).toBe(29);
});
it "converts a string to an integer", -> it("converts a string to an integer", function() {
model = new CourseGrader({weight: '7.0001', min_count: '3.67', drop_count: '1.88'}, {parse:true}) 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('weight')).toBe(7);
expect(model.get('min_count')).toBe(4) expect(model.get('min_count')).toBe(4);
expect(model.get('drop_count')).toBe(2) return expect(model.get('drop_count')).toBe(2);
});
it "does a no-op for integers", -> it("does a no-op for integers", function() {
model = new CourseGrader({weight: 7, min_count: 3, drop_count: 1}, {parse:true}) const model = new CourseGrader({weight: 7, min_count: 3, drop_count: 1}, {parse:true});
expect(model.get('weight')).toBe(7) expect(model.get('weight')).toBe(7);
expect(model.get('min_count')).toBe(3) expect(model.get('min_count')).toBe(3);
expect(model.get('drop_count')).toBe(1) return expect(model.get('drop_count')).toBe(1);
});
it "gives validation error if min_count is less than 1 or drop_count is NaN", -> return it("gives validation error if min_count is less than 1 or drop_count is NaN", function() {
model = new CourseGrader() const model = new CourseGrader();
errors = model.validate({min_count: 0, drop_count: ''}, {validate:true}) 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.min_count).toBe('Please enter an integer greater than 0.');
expect(errors.drop_count).toBe('Please enter non-negative integer.') expect(errors.drop_count).toBe('Please enter non-negative integer.');
# don't allow negative integers // don't allow negative integers
errors = model.validate({min_count: -12, drop_count: -1}, {validate:true}) 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.min_count).toBe('Please enter an integer greater than 0.');
expect(errors.drop_count).toBe('Please enter non-negative integer.') expect(errors.drop_count).toBe('Please enter non-negative integer.');
# don't allow floats // don't allow floats
errors = model.validate({min_count: 12.2, drop_count: 1.5}, {validate:true}) 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.min_count).toBe('Please enter an integer greater than 0.');
expect(errors.drop_count).toBe('Please enter non-negative integer.') return expect(errors.drop_count).toBe('Please enter non-negative integer.');
});
})
)
);
define ["underscore", "js/models/settings/course_grading_policy"], (_, CourseGradingPolicy) -> /*
describe "CourseGradingPolicy", -> * decaffeinate suggestions:
beforeEach -> * DS102: Remove unnecessary code created because of implicit returns
@model = new CourseGradingPolicy() * 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", -> describe("parse", () =>
it "sets a null grace period to 00:00", -> it("sets a null grace period to 00:00", function() {
attrs = @model.parse(grace_period: null) const attrs = this.model.parse({grace_period: null});
expect(attrs.grace_period).toEqual( return expect(attrs.grace_period).toEqual({
hours: 0, hours: 0,
minutes: 0 minutes: 0
) });
})
);
describe "parseGracePeriod", -> describe("parseGracePeriod", function() {
it "parses a time in HH:MM format", -> it("parses a time in HH:MM format", function() {
time = @model.parseGracePeriod("07:19") const time = this.model.parseGracePeriod("07:19");
expect(time).toEqual( return expect(time).toEqual({
hours: 7, hours: 7,
minutes: 19 minutes: 19
) });
});
it "returns null on an incorrectly formatted string", -> return it("returns null on an incorrectly formatted string", function() {
expect(@model.parseGracePeriod("asdf")).toBe(null) expect(this.model.parseGracePeriod("asdf")).toBe(null);
expect(@model.parseGracePeriod("7:19")).toBe(null) expect(this.model.parseGracePeriod("7:19")).toBe(null);
expect(@model.parseGracePeriod("1000:00")).toBe(null) return expect(this.model.parseGracePeriod("1000:00")).toBe(null);
});
});
describe "validate", -> return describe("validate", function() {
it "enforces that the passing grade is <= the minimum grade to receive credit if credit is enabled", -> it("enforces that the passing grade is <= the minimum grade to receive credit if credit is enabled", function() {
@model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: true}) this.model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: true});
@model.set('grade_cutoffs', [0.9], validate: true) this.model.set('grade_cutoffs', [0.9], {validate: true});
expect(_.keys(@model.validationError)).toContain('minimum_grade_credit') return expect(_.keys(this.model.validationError)).toContain('minimum_grade_credit');
});
it "does not enforce the passing grade limit in non-credit courses", -> return it("does not enforce the passing grade limit in non-credit courses", function() {
@model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: false}) this.model.set({minimum_grade_credit: 0.8, grace_period: '01:00', is_credit_course: false});
@model.set({grade_cutoffs: [0.9]}, validate: true) this.model.set({grade_cutoffs: [0.9]}, {validate: true});
expect(@model.validationError).toBe(null) return expect(this.model.validationError).toBe(null);
});
});
})
);
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", -> describe("FileUpload", function() {
beforeEach -> beforeEach(function() {
@model = new FileUpload() return this.model = new FileUpload();
});
it "is unfinished by default", -> it("is unfinished by default", function() {
expect(@model.get("finished")).toBeFalsy() return expect(this.model.get("finished")).toBeFalsy();
});
it "is not uploading by default", -> it("is not uploading by default", function() {
expect(@model.get("uploading")).toBeFalsy() return expect(this.model.get("uploading")).toBeFalsy();
});
it "is valid by default", -> it("is valid by default", function() {
expect(@model.isValid()).toBeTruthy() return expect(this.model.isValid()).toBeTruthy();
});
it "is valid for text files by default", -> it("is valid for text files by default", function() {
file = {"type": "text/plain", "name": "filename.txt"} const file = {"type": "text/plain", "name": "filename.txt"};
@model.set("selectedFile", file); this.model.set("selectedFile", file);
expect(@model.isValid()).toBeTruthy() return expect(this.model.isValid()).toBeTruthy();
});
it "is valid for PNG files by default", -> it("is valid for PNG files by default", function() {
file = {"type": "image/png", "name": "filename.png"} const file = {"type": "image/png", "name": "filename.png"};
@model.set("selectedFile", file); this.model.set("selectedFile", file);
expect(@model.isValid()).toBeTruthy() return expect(this.model.isValid()).toBeTruthy();
});
it "can accept a file type when explicitly set", -> it("can accept a file type when explicitly set", function() {
file = {"type": "image/png", "name": "filename.png"} const file = {"type": "image/png", "name": "filename.png"};
@model.set("mimeTypes": ["image/png"]) this.model.set({"mimeTypes": ["image/png"]});
@model.set("selectedFile", file) this.model.set("selectedFile", file);
expect(@model.isValid()).toBeTruthy() return expect(this.model.isValid()).toBeTruthy();
});
it "can accept a file format when explicitly set", -> it("can accept a file format when explicitly set", function() {
file = {"type": "", "name": "filename.png"} const file = {"type": "", "name": "filename.png"};
@model.set("fileFormats": ["png"]) this.model.set({"fileFormats": ["png"]});
@model.set("selectedFile", file) this.model.set("selectedFile", file);
expect(@model.isValid()).toBeTruthy() return expect(this.model.isValid()).toBeTruthy();
});
it "can accept multiple file types", -> it("can accept multiple file types", function() {
file = {"type": "image/gif", "name": "filename.gif"} const file = {"type": "image/gif", "name": "filename.gif"};
@model.set("mimeTypes": ["image/png", "image/jpeg", "image/gif"]) this.model.set({"mimeTypes": ["image/png", "image/jpeg", "image/gif"]});
@model.set("selectedFile", file) this.model.set("selectedFile", file);
expect(@model.isValid()).toBeTruthy() return expect(this.model.isValid()).toBeTruthy();
});
it "can accept multiple file formats", -> it("can accept multiple file formats", function() {
file = {"type": "image/gif", "name": "filename.gif"} const file = {"type": "image/gif", "name": "filename.gif"};
@model.set("fileFormats": ["png", "jpeg", "gif"]) this.model.set({"fileFormats": ["png", "jpeg", "gif"]});
@model.set("selectedFile", file) this.model.set("selectedFile", file);
expect(@model.isValid()).toBeTruthy() return expect(this.model.isValid()).toBeTruthy();
});
describe "fileTypes", -> describe("fileTypes", () =>
it "returns a list of the uploader's file types", -> it("returns a list of the uploader's file types", function() {
@model.set('mimeTypes', ['image/png', 'application/json']) this.model.set('mimeTypes', ['image/png', 'application/json']);
@model.set('fileFormats', ['gif', 'srt']) this.model.set('fileFormats', ['gif', 'srt']);
expect(@model.fileTypes()).toEqual(['PNG', 'JSON', 'GIF', 'SRT']) return expect(this.model.fileTypes()).toEqual(['PNG', 'JSON', 'GIF', 'SRT']);
})
);
describe "formatValidTypes", -> return describe("formatValidTypes", function() {
it "returns a map of formatted file types and extensions", -> it("returns a map of formatted file types and extensions", function() {
@model.set('mimeTypes', ['image/png', 'image/jpeg', 'application/json']) this.model.set('mimeTypes', ['image/png', 'image/jpeg', 'application/json']);
formatted = @model.formatValidTypes() const formatted = this.model.formatValidTypes();
expect(formatted).toEqual( return expect(formatted).toEqual({
fileTypes: 'PNG, JPEG or JSON', fileTypes: 'PNG, JPEG or JSON',
fileExtensions: '.png, .jpeg or .json' fileExtensions: '.png, .jpeg or .json'
) });
});
it "does not format with only one mime type", -> return it("does not format with only one mime type", function() {
@model.set('mimeTypes', ['application/pdf']) this.model.set('mimeTypes', ['application/pdf']);
formatted = @model.formatValidTypes() const formatted = this.model.formatValidTypes();
expect(formatted).toEqual( return expect(formatted).toEqual({
fileTypes: 'PDF', fileTypes: 'PDF',
fileExtensions: '.pdf' fileExtensions: '.pdf'
) });
});
});
})
);
class MinimaxProblemDisplay extends XProblemDisplay /*
* decaffeinate suggestions:
constructor: (@state, @submission, @evaluation, @container, @submissionField, @parameters={}) -> * DS001: Remove Babel/TypeScript constructor workaround
* DS102: Remove unnecessary code created because of implicit returns
super(@state, @submission, @evaluation, @container, @submissionField, @parameters) * DS205: Consider reworking code to avoid use of IIFEs
* DS207: Consider shorter variations of null checks
render: () -> * DS208: Avoid top-level this
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
createSubmission: () -> */
class MinimaxProblemDisplay extends XProblemDisplay {
@newSubmission = {}
constructor(state, submission, evaluation, container, submissionField, parameters) {
if @submission?
for id, value of @submission {
@newSubmission[id] = value // Hack: trick Babel/TypeScript into allowing this before super.
if (false) { super(); }
getCurrentSubmission: () -> let thisFn = (() => { this; }).toString();
return @newSubmission let thisName = thisFn.slice(thisFn.indexOf('{') + 1, thisFn.indexOf(';')).trim();
eval(`${thisName} = this;`);
root = exports ? this }
root.TestProblemDisplay = TestProblemDisplay this.state = state;
this.submission = submission;
this.evaluation = evaluation;
this.container = container;
this.submissionField = submissionField;
if (parameters == null) { parameters = {}; }
this.parameters = parameters;
super(this.state, this.submission, this.evaluation, this.container, this.submissionField, this.parameters);
}
render() {}
createSubmission() {
this.newSubmission = {};
if (this.submission != null) {
return (() => {
const result = [];
for (let id in this.submission) {
const value = this.submission[id];
result.push(this.newSubmission[id] = value);
}
return result;
})();
}
}
getCurrentSubmission() {
return this.newSubmission;
}
}
const root = typeof exports !== 'undefined' && exports !== null ? exports : this;
root.TestProblemDisplay = TestProblemDisplay;
class TestProblemGenerator extends XProblemGenerator /*
* decaffeinate suggestions:
* DS001: Remove Babel/TypeScript constructor workaround
* DS207: Consider shorter variations of null checks
* DS208: Avoid top-level this
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
class TestProblemGenerator extends XProblemGenerator {
constructor: (seed, @parameters = {}) -> constructor(seed, parameters) {
super(seed, @parameters) {
// Hack: trick Babel/TypeScript into allowing this before super.
if (false) { super(); }
let thisFn = (() => { this; }).toString();
let thisName = thisFn.slice(thisFn.indexOf('{') + 1, thisFn.indexOf(';')).trim();
eval(`${thisName} = this;`);
}
if (parameters == null) { parameters = {}; }
this.parameters = parameters;
super(seed, this.parameters);
}
generate: () -> generate() {
@problemState.value = @parameters.value this.problemState.value = this.parameters.value;
return @problemState return this.problemState;
}
}
root = exports ? this const root = typeof exports !== 'undefined' && exports !== null ? exports : this;
root.generatorClass = TestProblemGenerator root.generatorClass = TestProblemGenerator;
class TestProblemGrader extends XProblemGrader /*
* decaffeinate suggestions:
constructor: (@submission, @problemState, @parameters={}) -> * DS001: Remove Babel/TypeScript constructor workaround
* DS102: Remove unnecessary code created because of implicit returns
super(@submission, @problemState, @parameters) * DS207: Consider shorter variations of null checks
* DS208: Avoid top-level this
solve: () -> * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
@solution = {0: @problemState.value} class TestProblemGrader extends XProblemGrader {
grade: () -> constructor(submission, problemState, parameters) {
if not @solution? {
@solve() // Hack: trick Babel/TypeScript into allowing this before super.
if (false) { super(); }
allCorrect = true let thisFn = (() => { this; }).toString();
let thisName = thisFn.slice(thisFn.indexOf('{') + 1, thisFn.indexOf(';')).trim();
for id, value of @solution eval(`${thisName} = this;`);
valueCorrect = if @submission? then (value == @submission[id]) else false }
@evaluation[id] = valueCorrect this.submission = submission;
if not valueCorrect this.problemState = problemState;
allCorrect = false if (parameters == null) { parameters = {}; }
this.parameters = parameters;
return allCorrect super(this.submission, this.problemState, this.parameters);
}
root = exports ? this
root.graderClass = TestProblemGrader solve() {
return this.solution = {0: this.problemState.value};
}
grade() {
if ((this.solution == null)) {
this.solve();
}
let allCorrect = true;
for (let id in this.solution) {
const value = this.solution[id];
const valueCorrect = (this.submission != null) ? (value === this.submission[id]) : false;
this.evaluation[id] = valueCorrect;
if (!valueCorrect) {
allCorrect = false;
}
}
return allCorrect;
}
}
const root = typeof exports !== 'undefined' && exports !== null ? exports : this;
root.graderClass = TestProblemGrader;
class XProblemGenerator /*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* DS208: Avoid top-level this
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
class XProblemGenerator {
constructor: (seed, @parameters={}) -> constructor(seed, parameters) {
@random = new MersenneTwister(seed) if (parameters == null) { parameters = {}; }
this.parameters = parameters;
this.random = new MersenneTwister(seed);
@problemState = {} this.problemState = {};
}
generate: () -> generate() {
console.error("Abstract method called: XProblemGenerator.generate") return console.error("Abstract method called: XProblemGenerator.generate");
}
}
class XProblemDisplay class XProblemDisplay {
constructor: (@state, @submission, @evaluation, @container, @submissionField, @parameters={}) -> constructor(state, submission, evaluation, container, submissionField, parameters) {
this.state = state;
this.submission = submission;
this.evaluation = evaluation;
this.container = container;
this.submissionField = submissionField;
if (parameters == null) { parameters = {}; }
this.parameters = parameters;
}
render: () -> render() {
console.error("Abstract method called: XProblemDisplay.render") return console.error("Abstract method called: XProblemDisplay.render");
}
updateSubmission: () -> updateSubmission() {
@submissionField.val(JSON.stringify(@getCurrentSubmission())) return this.submissionField.val(JSON.stringify(this.getCurrentSubmission()));
}
getCurrentSubmission: () -> getCurrentSubmission() {
console.error("Abstract method called: XProblemDisplay.getCurrentSubmission") return console.error("Abstract method called: XProblemDisplay.getCurrentSubmission");
}
}
class XProblemGrader class XProblemGrader {
constructor: (@submission, @problemState, @parameters={}) -> constructor(submission, problemState, parameters) {
@solution = null this.submission = submission;
@evaluation = {} this.problemState = problemState;
if (parameters == null) { parameters = {}; }
this.parameters = parameters;
this.solution = null;
this.evaluation = {};
}
solve: () -> solve() {
console.error("Abstract method called: XProblemGrader.solve") return console.error("Abstract method called: XProblemGrader.solve");
}
grade: () -> grade() {
console.error("Abstract method called: XProblemGrader.grade") return console.error("Abstract method called: XProblemGrader.grade");
}
}
root = exports ? this const root = typeof exports !== 'undefined' && exports !== null ? exports : this;
root.XProblemGenerator = XProblemGenerator root.XProblemGenerator = XProblemGenerator;
root.XProblemDisplay = XProblemDisplay root.XProblemDisplay = XProblemDisplay;
root.XProblemGrader = XProblemGrader root.XProblemGrader = XProblemGrader;
describe 'Annotatable', -> /*
beforeEach -> * decaffeinate suggestions:
loadFixtures 'annotatable.html' * DS102: Remove unnecessary code created because of implicit returns
describe 'constructor', -> * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
el = $('.xblock-student_view.xmodule_AnnotatableModule') */
beforeEach -> describe('Annotatable', function() {
@annotatable = new Annotatable(el) beforeEach(() => loadFixtures('annotatable.html'));
it 'works', -> return describe('constructor', function() {
expect(1).toBe(1) const el = $('.xblock-student_view.xmodule_AnnotatableModule');
beforeEach(function() {
return this.annotatable = new Annotatable(el);
});
return it('works', () => expect(1).toBe(1));
});
});
describe 'HTMLEditingDescriptor', -> /*
beforeEach -> * decaffeinate suggestions:
window.baseUrl = "/static/deadbeef" * DS102: Remove unnecessary code created because of implicit returns
afterEach -> * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
delete window.baseUrl */
describe 'Visual HTML Editor', -> describe('HTMLEditingDescriptor', function() {
beforeEach -> beforeEach(() => window.baseUrl = "/static/deadbeef");
loadFixtures 'html-edit-visual.html' afterEach(() => delete window.baseUrl);
@descriptor = new HTMLEditingDescriptor($('.test-component')) describe('Visual HTML Editor', function() {
it 'Returns data from Visual Editor if text has changed', -> beforeEach(function() {
visualEditorStub = loadFixtures('html-edit-visual.html');
getContent: () -> 'from visual editor' return this.descriptor = new HTMLEditingDescriptor($('.test-component'));
spyOn(@descriptor, 'getVisualEditor').and.callFake () -> });
visualEditorStub it('Returns data from Visual Editor if text has changed', function() {
data = @descriptor.save().data const visualEditorStub =
expect(data).toEqual('from visual editor') {getContent() { return 'from visual editor'; }};
it 'Returns data from Raw Editor if text has not changed', -> spyOn(this.descriptor, 'getVisualEditor').and.callFake(() => visualEditorStub);
visualEditorStub = const { data } = this.descriptor.save();
getContent: () -> '<p>original visual text</p>' return expect(data).toEqual('from visual editor');
spyOn(@descriptor, 'getVisualEditor').and.callFake () -> });
visualEditorStub it('Returns data from Raw Editor if text has not changed', function() {
data = @descriptor.save().data const visualEditorStub =
expect(data).toEqual('raw text') {getContent() { return '<p>original visual text</p>'; }};
it 'Performs link rewriting for static assets when saving', -> spyOn(this.descriptor, 'getVisualEditor').and.callFake(() => visualEditorStub);
visualEditorStub = const { data } = this.descriptor.save();
getContent: () -> 'from visual editor with /c4x/foo/bar/asset/image.jpg' return expect(data).toEqual('raw text');
spyOn(@descriptor, 'getVisualEditor').and.callFake () -> });
visualEditorStub it('Performs link rewriting for static assets when saving', function() {
data = @descriptor.save().data const visualEditorStub =
expect(data).toEqual('from visual editor with /static/image.jpg') {getContent() { return 'from visual editor with /c4x/foo/bar/asset/image.jpg'; }};
it 'When showing visual editor links are rewritten to c4x format', -> spyOn(this.descriptor, 'getVisualEditor').and.callFake(() => visualEditorStub);
visualEditorStub = const { data } = this.descriptor.save();
content: 'text /static/image.jpg' return expect(data).toEqual('from visual editor with /static/image.jpg');
startContent: 'text /static/image.jpg' });
focus: -> it('When showing visual editor links are rewritten to c4x format', function() {
setContent: (x) -> @content = x const visualEditorStub = {
getContent: -> @content content: 'text /static/image.jpg',
startContent: 'text /static/image.jpg',
focus() {},
setContent(x) { return this.content = x; },
getContent() { return this.content; }
};
@descriptor.initInstanceCallback(visualEditorStub) this.descriptor.initInstanceCallback(visualEditorStub);
expect(visualEditorStub.getContent()).toEqual('text /c4x/foo/bar/asset/image.jpg') return expect(visualEditorStub.getContent()).toEqual('text /c4x/foo/bar/asset/image.jpg');
it 'Enables spellcheck', -> });
expect($('.html-editor iframe')[0].contentDocument.body.spellcheck).toBe(true) return it('Enables spellcheck', () => expect($('.html-editor iframe')[0].contentDocument.body.spellcheck).toBe(true));
describe 'Raw HTML Editor', -> });
beforeEach -> return describe('Raw HTML Editor', function() {
loadFixtures 'html-editor-raw.html' beforeEach(function() {
@descriptor = new HTMLEditingDescriptor($('.test-component')) loadFixtures('html-editor-raw.html');
it 'Returns data from raw editor', -> return this.descriptor = new HTMLEditingDescriptor($('.test-component'));
data = @descriptor.save().data });
expect(data).toEqual('raw text') return it('Returns data from raw editor', function() {
const { data } = this.descriptor.save();
return expect(data).toEqual('raw text');
});
});
});
describe "TabsEditingDescriptor", -> /*
beforeEach -> * decaffeinate suggestions:
@isInactiveClass = "is-inactive" * DS102: Remove unnecessary code created because of implicit returns
@isCurrent = "current" * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
loadFixtures 'tabs-edit.html' */
@descriptor = new TabsEditingDescriptor($('.xblock')) describe("TabsEditingDescriptor", function() {
@html_id = 'test_id' beforeEach(function() {
@tab_0_switch = jasmine.createSpy('tab_0_switch'); this.isInactiveClass = "is-inactive";
@tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate'); this.isCurrent = "current";
@tab_1_switch = jasmine.createSpy('tab_1_switch'); loadFixtures('tabs-edit.html');
@tab_1_modelUpdate = jasmine.createSpy('tab_1_modelUpdate'); this.descriptor = new TabsEditingDescriptor($('.xblock'));
TabsEditingDescriptor.Model.addModelUpdate(@html_id, 'Tab 0 Editor', @tab_0_modelUpdate) this.html_id = 'test_id';
TabsEditingDescriptor.Model.addOnSwitch(@html_id, 'Tab 0 Editor', @tab_0_switch) this.tab_0_switch = jasmine.createSpy('tab_0_switch');
TabsEditingDescriptor.Model.addModelUpdate(@html_id, 'Tab 1 Transcripts', @tab_1_modelUpdate) this.tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate');
TabsEditingDescriptor.Model.addOnSwitch(@html_id, 'Tab 1 Transcripts', @tab_1_switch) 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, 'hide').and.callThrough();
spyOn($.fn, 'show').and.callThrough() spyOn($.fn, 'show').and.callThrough();
spyOn(TabsEditingDescriptor.Model, 'initialize') spyOn(TabsEditingDescriptor.Model, 'initialize');
spyOn(TabsEditingDescriptor.Model, 'updateValue') return spyOn(TabsEditingDescriptor.Model, 'updateValue');
});
afterEach -> afterEach(() => TabsEditingDescriptor.Model.modules= {});
TabsEditingDescriptor.Model.modules= {}
describe "constructor", -> describe("constructor", () =>
it "first tab should be visible", -> it("first tab should be visible", function() {
expect(@descriptor.$tabs.first()).toHaveClass(@isCurrent) expect(this.descriptor.$tabs.first()).toHaveClass(this.isCurrent);
expect(@descriptor.$content.first()).not.toHaveClass(@isInactiveClass) return expect(this.descriptor.$content.first()).not.toHaveClass(this.isInactiveClass);
})
);
describe "onSwitchEditor", -> describe("onSwitchEditor", function() {
it "switching tabs changes styles", -> it("switching tabs changes styles", function() {
@descriptor.$tabs.eq(1).trigger("click") this.descriptor.$tabs.eq(1).trigger("click");
expect(@descriptor.$tabs.eq(0)).not.toHaveClass(@isCurrent) expect(this.descriptor.$tabs.eq(0)).not.toHaveClass(this.isCurrent);
expect(@descriptor.$content.eq(0)).toHaveClass(@isInactiveClass) expect(this.descriptor.$content.eq(0)).toHaveClass(this.isInactiveClass);
expect(@descriptor.$tabs.eq(1)).toHaveClass(@isCurrent) expect(this.descriptor.$tabs.eq(1)).toHaveClass(this.isCurrent);
expect(@descriptor.$content.eq(1)).not.toHaveClass(@isInactiveClass) expect(this.descriptor.$content.eq(1)).not.toHaveClass(this.isInactiveClass);
expect(@tab_1_switch).toHaveBeenCalled() return expect(this.tab_1_switch).toHaveBeenCalled();
});
it "if click on current tab, nothing should happen", -> it("if click on current tab, nothing should happen", function() {
spyOn($.fn, 'trigger').and.callThrough() spyOn($.fn, 'trigger').and.callThrough();
currentTab = @descriptor.$tabs.filter('.' + @isCurrent) const currentTab = this.descriptor.$tabs.filter(`.${this.isCurrent}`);
@descriptor.$tabs.eq(0).trigger("click") this.descriptor.$tabs.eq(0).trigger("click");
expect(@descriptor.$tabs.filter('.' + @isCurrent)).toEqual(currentTab) expect(this.descriptor.$tabs.filter(`.${this.isCurrent}`)).toEqual(currentTab);
expect($.fn.trigger.calls.count()).toEqual(1) return expect($.fn.trigger.calls.count()).toEqual(1);
});
it "onSwitch function call", -> return it("onSwitch function call", function() {
@descriptor.$tabs.eq(1).trigger("click") this.descriptor.$tabs.eq(1).trigger("click");
expect(TabsEditingDescriptor.Model.updateValue).toHaveBeenCalled() expect(TabsEditingDescriptor.Model.updateValue).toHaveBeenCalled();
expect(@tab_1_switch).toHaveBeenCalled() return expect(this.tab_1_switch).toHaveBeenCalled();
});
});
describe "save", -> return describe("save", function() {
it "function for current tab should be called", -> it("function for current tab should be called", function() {
@descriptor.$tabs.eq(1).trigger("click") this.descriptor.$tabs.eq(1).trigger("click");
data = @descriptor.save().data const { data } = this.descriptor.save();
expect(@tab_1_modelUpdate).toHaveBeenCalled() return expect(this.tab_1_modelUpdate).toHaveBeenCalled();
});
it "detach click event", -> return it("detach click event", function() {
spyOn($.fn, "off") spyOn($.fn, "off");
@descriptor.save() this.descriptor.save();
expect($.fn.off).toHaveBeenCalledWith( return expect($.fn.off).toHaveBeenCalledWith(
'click', 'click',
'.editor-tabs .tab', '.editor-tabs .tab',
@descriptor.onSwitchEditor this.descriptor.onSwitchEditor
) );
});
});
});
describe "TabsEditingDescriptor special save cases", -> describe("TabsEditingDescriptor special save cases", function() {
beforeEach -> beforeEach(function() {
@isInactiveClass = "is-inactive" this.isInactiveClass = "is-inactive";
@isCurrent = "current" this.isCurrent = "current";
loadFixtures 'tabs-edit.html' loadFixtures('tabs-edit.html');
@descriptor = new window.TabsEditingDescriptor($('.xblock')) this.descriptor = new window.TabsEditingDescriptor($('.xblock'));
@html_id = 'test_id' return this.html_id = 'test_id';
});
describe "save", -> return describe("save", function() {
it "case: no init", -> it("case: no init", function() {
data = @descriptor.save().data const { data } = this.descriptor.save();
expect(data).toEqual(null) return expect(data).toEqual(null);
});
it "case: no function in model update", -> it("case: no function in model update", function() {
TabsEditingDescriptor.Model.initialize(@html_id) TabsEditingDescriptor.Model.initialize(this.html_id);
data = @descriptor.save().data const { data } = this.descriptor.save();
expect(data).toEqual(null) return expect(data).toEqual(null);
});
it "case: no function in model update, but value presented", -> return it("case: no function in model update, but value presented", function() {
@tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate').and.returnValue(1) this.tab_0_modelUpdate = jasmine.createSpy('tab_0_modelUpdate').and.returnValue(1);
TabsEditingDescriptor.Model.addModelUpdate(@html_id, 'Tab 0 Editor', @tab_0_modelUpdate) TabsEditingDescriptor.Model.addModelUpdate(this.html_id, 'Tab 0 Editor', this.tab_0_modelUpdate);
@descriptor.$tabs.eq(1).trigger("click") this.descriptor.$tabs.eq(1).trigger("click");
expect(@tab_0_modelUpdate).toHaveBeenCalled() expect(this.tab_0_modelUpdate).toHaveBeenCalled();
data = @descriptor.save().data const { data } = this.descriptor.save();
expect(data).toEqual(1) return expect(data).toEqual(1);
});
});
});
describe "$.immediateDescendents", -> /*
beforeEach -> * decaffeinate suggestions:
setFixtures """ * DS102: Remove unnecessary code created because of implicit returns
<div> * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
<div class='xblock' id='child'> */
<div class='xblock' id='nested'/> describe("$.immediateDescendents", function() {
</div> beforeEach(function() {
<div> setFixtures(`\
<div class='xblock' id='grandchild'/> <div>
</div> <div class='xblock' id='child'>
</div> <div class='xblock' id='nested'/>
""" </div>
<div>
<div class='xblock' id='grandchild'/>
</div>
</div>\
`
);
@descendents = $('#jasmine-fixtures').immediateDescendents(".xblock").get() return this.descendents = $('#jasmine-fixtures').immediateDescendents(".xblock").get();
});
it "finds non-immediate children", -> it("finds non-immediate children", function() {
expect(@descendents).toContain($('#grandchild').get(0)) return expect(this.descendents).toContain($('#grandchild').get(0));
});
it "finds immediate children", -> it("finds immediate children", function() {
expect(@descendents).toContain($('#child').get(0)) return expect(this.descendents).toContain($('#child').get(0));
});
it "skips nested descendents", -> it("skips nested descendents", function() {
expect(@descendents).not.toContain($('#nested').get(0)) return expect(this.descendents).not.toContain($('#nested').get(0));
});
it "finds 2 children", -> return it("finds 2 children", function() {
expect(@descendents.length).toBe(2) return expect(this.descendents.length).toBe(2);
\ No newline at end of file });
});
\ No newline at end of file
describe 'Courseware', -> /*
describe 'start', -> * decaffeinate suggestions:
it 'binds the Logger', -> * DS102: Remove unnecessary code created because of implicit returns
spyOn(Logger, 'bind') * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
Courseware.start() */
expect(Logger.bind).toHaveBeenCalled() describe('Courseware', function() {
describe('start', () =>
it('binds the Logger', function() {
spyOn(Logger, 'bind');
Courseware.start();
return expect(Logger.bind).toHaveBeenCalled();
})
);
describe 'render', -> return describe('render', function() {
beforeEach -> beforeEach(function() {
jasmine.stubRequests() jasmine.stubRequests();
@courseware = new Courseware this.courseware = new Courseware;
spyOn(window, 'Histogram') spyOn(window, 'Histogram');
spyOn(window, 'Problem') spyOn(window, 'Problem');
spyOn(window, 'Video') spyOn(window, 'Video');
spyOn(XBlock, 'initializeBlocks') spyOn(XBlock, 'initializeBlocks');
setFixtures """ setFixtures(`\
<div class="course-content"> <div class="course-content">
<div id="video_1" class="video" data-streams="1.0:abc1234"></div> <div id="video_1" class="video" data-streams="1.0:abc1234"></div>
<div id="video_2" class="video" data-streams="1.0:def5678"></div> <div id="video_2" class="video" data-streams="1.0:def5678"></div>
<div id="problem_3" class="problems-wrapper" data-problem-id="3" data-url="/example/url/"> <div id="problem_3" class="problems-wrapper" data-problem-id="3" data-url="/example/url/">
<div id="histogram_3" class="histogram" data-histogram="[[0, 1]]" style="height: 20px; display: block;"> <div id="histogram_3" class="histogram" data-histogram="[[0, 1]]" style="height: 20px; display: block;">
</div> </div>
</div> </div>\
""" `
@courseware.render() );
return this.courseware.render();
});
it 'ensure that the XModules have been loaded', -> it('ensure that the XModules have been loaded', () => expect(XBlock.initializeBlocks).toHaveBeenCalled());
expect(XBlock.initializeBlocks).toHaveBeenCalled()
it 'detect the histrogram element and convert it', -> return it('detect the histrogram element and convert it', () => expect(window.Histogram).toHaveBeenCalledWith('3', [[0, 1]]));
expect(window.Histogram).toHaveBeenCalledWith('3', [[0, 1]]) });
});
describe 'FeedbackForm', -> /*
beforeEach -> * decaffeinate suggestions:
loadFixtures 'coffee/fixtures/feedback_form.html' * 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', -> return describe('constructor', function() {
beforeEach -> beforeEach(function() {
new FeedbackForm new FeedbackForm;
spyOn($, 'postWithPrefix').and.callFake (url, data, callback, format) -> return spyOn($, 'postWithPrefix').and.callFake((url, data, callback, format) => callback());
callback() });
it 'post data to /send_feedback on click', -> it('post data to /send_feedback on click', function() {
$('#feedback_subject').val 'Awesome!' $('#feedback_subject').val('Awesome!');
$('#feedback_message').val 'This site is really good.' $('#feedback_message').val('This site is really good.');
$('#feedback_button').click() $('#feedback_button').click();
expect($.postWithPrefix).toHaveBeenCalledWith '/send_feedback', { return expect($.postWithPrefix).toHaveBeenCalledWith('/send_feedback', {
subject: 'Awesome!' subject: 'Awesome!',
message: 'This site is really good.' message: 'This site is really good.',
url: window.location.href url: window.location.href
}, jasmine.any(Function), 'json' }, jasmine.any(Function), 'json');
});
it 'replace the form with a thank you message', -> return it('replace the form with a thank you message', function() {
$('#feedback_button').click() $('#feedback_button').click();
expect($('#feedback_div').html()).toEqual 'Feedback submitted. Thank you' return expect($('#feedback_div').html()).toEqual('Feedback submitted. Thank you');
});
});
});
jasmine.stubbedMetadata = /*
slowerSpeedYoutubeId: * decaffeinate suggestions:
id: 'slowerSpeedYoutubeId' * 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 duration: 300
normalSpeedYoutubeId: },
id: 'normalSpeedYoutubeId' normalSpeedYoutubeId: {
id: 'normalSpeedYoutubeId',
duration: 200 duration: 200
bogus: },
bogus: {
duration: 100 duration: 100
}
};
jasmine.stubbedCaption = jasmine.stubbedCaption = {
start: [0, 10000, 20000, 30000] start: [0, 10000, 20000, 30000],
text: ['Caption at 0', 'Caption at 10000', 'Caption at 20000', 'Caption at 30000'] text: ['Caption at 0', 'Caption at 10000', 'Caption at 20000', 'Caption at 30000']
};
jasmine.stubRequests = -> jasmine.stubRequests = () =>
spyOn($, 'ajax').and.callFake (settings) -> spyOn($, 'ajax').and.callFake(function(settings) {
if match = settings.url.match /youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/ let match;
settings.success data: jasmine.stubbedMetadata[match[1]] if (match = settings.url.match(/youtube\.com\/.+\/videos\/(.+)\?v=2&alt=jsonc/)) {
else if match = settings.url.match /static\/subs\/(.+)\.srt\.sjson/ return settings.success({data: jasmine.stubbedMetadata[match[1]]});
settings.success jasmine.stubbedCaption } else if (match = settings.url.match(/static\/subs\/(.+)\.srt\.sjson/)) {
else if settings.url.match /modx\/.+\/problem_get$/ return settings.success(jasmine.stubbedCaption);
settings.success html: readFixtures('problem_content.html') } else if (settings.url.match(/modx\/.+\/problem_get$/)) {
else if settings.url == '/calculate' || return settings.success({html: readFixtures('problem_content.html')});
} else if ((settings.url === '/calculate') ||
settings.url.match(/modx\/.+\/goto_position$/) || settings.url.match(/modx\/.+\/goto_position$/) ||
settings.url.match(/event$/) || settings.url.match(/event$/) ||
settings.url.match(/modx\/.+\/problem_(check|reset|show|save)$/) settings.url.match(/modx\/.+\/problem_(check|reset|show|save)$/)) {
# do nothing // do nothing
else } else {
throw "External request attempted for #{settings.url}, which is not defined." throw `External request attempted for ${settings.url}, which is not defined.`;
}
})
;
jasmine.stubYoutubePlayer = -> jasmine.stubYoutubePlayer = () =>
YT.Player = -> jasmine.createSpyObj 'YT.Player', ['cueVideoById', 'getVideoEmbedCode', YT.Player = () => jasmine.createSpyObj('YT.Player', ['cueVideoById', 'getVideoEmbedCode',
'getCurrentTime', 'getPlayerState', 'getVolume', 'setVolume', 'loadVideoById', 'getCurrentTime', 'getPlayerState', 'getVolume', 'setVolume', 'loadVideoById',
'playVideo', 'pauseVideo', 'seekTo'] 'playVideo', 'pauseVideo', 'seekTo'])
;
jasmine.stubVideoPlayer = (context, enableParts, createPlayer=true) -> jasmine.stubVideoPlayer = function(context, enableParts, createPlayer) {
enableParts = [enableParts] unless $.isArray(enableParts) let currentPartName;
if (createPlayer == null) { createPlayer = true; }
if (!$.isArray(enableParts)) { enableParts = [enableParts]; }
suite = context.suite let { suite } = context;
currentPartName = suite.description while suite = suite.parentSuite while ((suite = suite.parentSuite)) { currentPartName = suite.description; }
enableParts.push currentPartName enableParts.push(currentPartName);
for part in ['VideoCaption', 'VideoSpeedControl', 'VideoVolumeControl', 'VideoProgressSlider'] for (let part of ['VideoCaption', 'VideoSpeedControl', 'VideoVolumeControl', 'VideoProgressSlider']) {
unless $.inArray(part, enableParts) >= 0 if (!($.inArray(part, enableParts) >= 0)) {
spyOn window, part spyOn(window, part);
}
}
loadFixtures 'video.html' loadFixtures('video.html');
jasmine.stubRequests() jasmine.stubRequests();
YT.Player = undefined YT.Player = undefined;
context.video = new Video 'example', '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId' context.video = new Video('example', '.75:slowerSpeedYoutubeId,1.0:normalSpeedYoutubeId');
jasmine.stubYoutubePlayer() jasmine.stubYoutubePlayer();
if createPlayer if (createPlayer) {
return new VideoPlayer(video: context.video) return new VideoPlayer({video: context.video});
}
};
# Stub Youtube API // Stub Youtube API
window.YT = window.YT = {
PlayerState: PlayerState: {
UNSTARTED: -1 UNSTARTED: -1,
ENDED: 0 ENDED: 0,
PLAYING: 1 PLAYING: 1,
PAUSED: 2 PAUSED: 2,
BUFFERING: 3 BUFFERING: 3,
CUED: 5 CUED: 5
}
};
# Stub jQuery.cookie // Stub jQuery.cookie
$.cookie = jasmine.createSpy('jQuery.cookie').and.returnValue '1.0' $.cookie = jasmine.createSpy('jQuery.cookie').and.returnValue('1.0');
# Stub jQuery.qtip // Stub jQuery.qtip
$.fn.qtip = jasmine.createSpy 'jQuery.qtip' $.fn.qtip = jasmine.createSpy('jQuery.qtip');
# Stub jQuery.scrollTo // Stub jQuery.scrollTo
$.fn.scrollTo = jasmine.createSpy 'jQuery.scrollTo' $.fn.scrollTo = jasmine.createSpy('jQuery.scrollTo');
describe 'Histogram', -> /*
beforeEach -> * decaffeinate suggestions:
spyOn $, 'plot' * DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
describe 'constructor', -> */
it 'instantiate the data arrays', -> describe('Histogram', function() {
histogram = new Histogram 1, [] beforeEach(() => spyOn($, 'plot'));
expect(histogram.xTicks).toEqual []
expect(histogram.yTicks).toEqual [] describe('constructor', () =>
expect(histogram.data).toEqual [] it('instantiate the data arrays', function() {
const histogram = new Histogram(1, []);
describe 'calculate', -> expect(histogram.xTicks).toEqual([]);
beforeEach -> expect(histogram.yTicks).toEqual([]);
@histogram = new Histogram(1, [[null, 1], [1, 1], [2, 2], [3, 3]]) return expect(histogram.data).toEqual([]);
})
it 'store the correct value for data', -> );
expect(@histogram.data).toEqual [[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]]
describe('calculate', function() {
it 'store the correct value for x ticks', -> beforeEach(function() {
expect(@histogram.xTicks).toEqual [[1, '1'], [2, '2'], [3, '3']] return this.histogram = new Histogram(1, [[null, 1], [1, 1], [2, 2], [3, 3]]);
});
it 'store the correct value for y ticks', ->
expect(@histogram.yTicks).toEqual 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)]]);
describe 'render', -> });
it 'call flot with correct option', ->
new Histogram(1, [[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']]);
firstArg = $.plot.calls.mostRecent().args[0] });
secondArg = $.plot.calls.mostRecent().args[1]
thirdArg = $.plot.calls.mostRecent().args[2] return it('store the correct value for y ticks', function() {
return expect(this.histogram.yTicks).toEqual;
expect(firstArg.selector).toEqual($("#histogram_1").selector) });
expect(secondArg).toEqual([ });
data: [[1, Math.log(2)], [2, Math.log(3)], [3, Math.log(4)]]
bars: return describe('render', () =>
show: true it('call flot with correct option', function() {
align: 'center' new Histogram(1, [[1, 1], [2, 2], [3, 3]]);
lineWidth: 0
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,
fill: 1.0 fill: 1.0
},
color: "#b72121" color: "#b72121"
]) }
expect(thirdArg).toEqual( ]);
xaxis: return expect(thirdArg).toEqual({
min: -1 xaxis: {
max: 4 min: -1,
ticks: [[1, '1'], [2, '2'], [3, '3']] max: 4,
ticks: [[1, '1'], [2, '2'], [3, '3']],
tickLength: 0 tickLength: 0
yaxis: },
min: 0.0 yaxis: {
max: Math.log(4) * 1.1 min: 0.0,
ticks: [[Math.log(2), '1'], [Math.log(3), '2'], [Math.log(4), '3']] max: Math.log(4) * 1.1,
ticks: [[Math.log(2), '1'], [Math.log(3), '2'], [Math.log(4), '3']],
labelWidth: 50 labelWidth: 50
) }
});
})
);
});
describe 'Tab', -> /*
beforeEach -> * decaffeinate suggestions:
loadFixtures 'coffee/fixtures/tab.html' * DS102: Remove unnecessary code created because of implicit returns
@items = $.parseJSON readFixtures('coffee/fixtures/items.json') * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
describe 'constructor', -> describe('Tab', function() {
beforeEach -> beforeEach(function() {
spyOn($.fn, 'tabs') loadFixtures('coffee/fixtures/tab.html');
@tab = new Tab 1, @items return this.items = $.parseJSON(readFixtures('coffee/fixtures/items.json'));
});
it 'set the element', ->
expect(@tab.el).toEqual $('#tab_1') describe('constructor', function() {
beforeEach(function() {
it 'build the tabs', -> spyOn($.fn, 'tabs');
links = $('.navigation li>a').map(-> $(this).attr('href')).get() return this.tab = new Tab(1, this.items);
expect(links).toEqual ['#tab-1-0', '#tab-1-1', '#tab-1-2'] });
it 'build the container', -> it('set the element', function() {
containers = $('section').map(-> $(this).attr('id')).get() return expect(this.tab.el).toEqual($('#tab_1'));
expect(containers).toEqual ['tab-1-0', 'tab-1-1', 'tab-1-2'] });
it 'bind the tabs', -> it('build the tabs', function() {
expect($.fn.tabs).toHaveBeenCalledWith show: @tab.onShow 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']);
# 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, it('build the container', function() {
# but note that onShow will NOT be called when the user const containers = $('section').map(function() { return $(this).attr('id'); }).get();
# clicks on the tab if we're using jQuery version >= 1.9 return expect(containers).toEqual(['tab-1-0', 'tab-1-1', 'tab-1-2']);
describe 'onShow', -> });
beforeEach ->
@tab = new Tab 1, @items return it('bind the tabs', function() {
@tab.onShow($('#tab-1-0'), {'index': 1}) return expect($.fn.tabs).toHaveBeenCalledWith({show: this.tab.onShow});
});
it 'replace content in the container', -> });
@tab.onShow($('#tab-1-1'), {'index': 1})
expect($('#tab-1-0').html()).toEqual '' // As of jQuery 1.9, the onShow callback is deprecated
expect($('#tab-1-1').html()).toEqual 'Video 2' // http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate
expect($('#tab-1-2').html()).toEqual '' // The code below tests that onShow does what is expected,
// but note that onShow will NOT be called when the user
it 'trigger contentChanged event on the element', -> // clicks on the tab if we're using jQuery version >= 1.9
spyOnEvent @tab.el, 'contentChanged' return describe('onShow', function() {
@tab.onShow($('#tab-1-1'), {'index': 1}) beforeEach(function() {
expect('contentChanged').toHaveBeenTriggeredOn @tab.el this.tab = new Tab(1, this.items);
return this.tab.onShow($('#tab-1-0'), {'index': 1});
});
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('');
});
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);
});
});
});
describe "RequireJS namespacing", -> /*
beforeEach -> * decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
# Jasmine does not provide a way to use the typeof operator. We need * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
# to create our own custom matchers so that a TypeError is not thrown. */
jasmine.addMatchers describe("RequireJS namespacing", function() {
requirejsTobeUndefined: -> beforeEach(() =>
{
compare: -> // 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.
pass: typeof requirejs is "undefined" jasmine.addMatchers({
} requirejsTobeUndefined() {
return {
compare() {
return {
pass: typeof requirejs === "undefined"
};
} }
};
requireTobeUndefined: -> },
{
compare: -> requireTobeUndefined() {
{ return {
pass: typeof require is "undefined" compare() {
} return {
pass: typeof require === "undefined"
};
} }
};
defineTobeUndefined: -> },
{
compare: -> defineTobeUndefined() {
{ return {
pass: typeof define is "undefined" 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));
it "check that requirejs(), require(), and define() are not in the global namespace", -> return expect(window.RequireJS).toEqual(jasmine.any(Object));
});
# The custom matchers that we defined in the beforeEach() function do
# not operate on an object. We pass a dummy empty object {} not to return it("check that requirejs(), require(), and define() are not in the global namespace", function() {
# confuse Jasmine.
expect({}).requirejsTobeUndefined() // The custom matchers that we defined in the beforeEach() function do
expect({}).requireTobeUndefined() // not operate on an object. We pass a dummy empty object {} not to
expect({}).defineTobeUndefined() // confuse Jasmine.
expect(window.requirejs).not.toBeDefined() expect({}).requirejsTobeUndefined();
expect(window.require).not.toBeDefined() expect({}).requireTobeUndefined();
expect(window.define).not.toBeDefined() expect({}).defineTobeUndefined();
expect(window.requirejs).not.toBeDefined();
expect(window.require).not.toBeDefined();
describe "RequireJS module creation", -> return expect(window.define).not.toBeDefined();
inDefineCallback = undefined });
inRequireCallback = undefined });
it "check that we can use RequireJS to define() and require() a module", (done) ->
d1 = $.Deferred()
d2 = $.Deferred() describe("RequireJS module creation", function() {
# Because Require JS works asynchronously when defining and requiring let inDefineCallback = undefined;
# modules, we need to use the special Jasmine functions runs(), and let inRequireCallback = undefined;
# waitsFor() to set up this test. return it("check that we can use RequireJS to define() and require() a module", function(done) {
func = () -> const d1 = $.Deferred();
const d2 = $.Deferred();
# Initialize the variable that we will test for. They will be set // Because Require JS works asynchronously when defining and requiring
# to true in the appropriate callback functions called by Require // modules, we need to use the special Jasmine functions runs(), and
# JS. If their values do not change, this will mean that something // waitsFor() to set up this test.
# is not working as is intended. const func = function() {
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
# Define our test module. // JS. If their values do not change, this will mean that something
RequireJS.define "test_module", [], -> // is not working as is intended.
inDefineCallback = true inDefineCallback = false;
inRequireCallback = false;
d1.resolve()
// Define our test module.
# This module returns an object. It can be accessed via the RequireJS.define("test_module", [], function() {
# Require JS require() function. inDefineCallback = true;
module_status: "OK"
d1.resolve();
# Require our defined test module. // This module returns an object. It can be accessed via the
RequireJS.require ["test_module"], (test_module) -> // Require JS require() function.
inRequireCallback = true return {module_status: "OK"};
});
# If our test module was defined properly, then we should
# be able to get the object it returned, and query some
# property. // Require our defined test module.
expect(test_module.module_status).toBe "OK" return RequireJS.require(["test_module"], function(test_module) {
inRequireCallback = true;
d2.resolve()
// If our test module was defined properly, then we should
func() // be able to get the object it returned, and query some
# We will wait before checking if our module was defined and that we were able to require() the module. // property.
$.when(d1, d2).done(-> expect(test_module.module_status).toBe("OK");
# The final test behavior
expect(inDefineCallback).toBeTruthy() return d2.resolve();
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);
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment