define ["backbone", "js/models/textbook", "js/collections/textbook", "js/models/chapter", "js/collections/chapter", "coffee/src/main"], (Backbone, Textbook, TextbookSet, Chapter, ChapterSet, main) -> beforeEach -> @addMatchers toBeInstanceOf: (expected) -> return @actual instanceof expected describe "Textbook model", -> beforeEach -> main() @model = new Textbook() describe "Basic", -> it "should have an empty name by default", -> expect(@model.get("name")).toEqual("") it "should not show chapters by default", -> expect(@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 be empty by default", -> expect(@model.isEmpty()).toBeTruthy() it "should have a URL set", -> expect(@model.url()).toBeTruthy() it "should be able to reset itself", -> @model.set("name", "foobar") @model.reset() expect(@model.get("name")).toEqual("") it "should not be dirty by default", -> expect(@model.isDirty()).toBeFalsy() it "should be dirty after it's been changed", -> @model.set("name", "foobar") expect(@model.isDirty()).toBeTruthy() it "should not be dirty after calling setOriginalAttributes", -> @model.set("name", "foobar") @model.setOriginalAttributes() expect(@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 it "should match server model to client model", -> serverModelSpec = { "tab_title": "My Textbook", "chapters": [ {"title": "Chapter 1", "url": "/ch1.pdf"}, {"title": "Chapter 2", "url": "/ch2.pdf"}, ] } clientModelSpec = { "name": "My Textbook", "showChapters": false, "editing": false, "chapters": [{ "name": "Chapter 1", "asset_path": "/ch1.pdf", "order": 1 }, { "name": "Chapter 2", "asset_path": "/ch2.pdf", "order": 2 } ] } model = new Textbook(serverModelSpec, {parse: true}) expect(deepAttributes(model)).toEqual(clientModelSpec) expect(model.toJSON()).toEqual(serverModelSpec) describe "Validation", -> it "requires a name", -> model = new Textbook({name: ""}) 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 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 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 "can pass validation", -> chapter = new Chapter() chapter.isValid = -> true model = new Textbook({name: "foo"}) model.get("chapters").reset([chapter]) expect(model.isValid()).toBeTruthy() describe "Textbook collection", -> beforeEach -> CMS.URL.TEXTBOOKS = "/textbooks" @collection = new TextbookSet() afterEach -> delete CMS.URL.TEXTBOOKS it "should have a url set", -> expect(@collection.url()).toEqual("/textbooks") it "can call save", -> spyOn(@collection, "sync") @collection.save() expect(@collection.sync).toHaveBeenCalledWith("update", @collection, undefined) describe "Chapter model", -> beforeEach -> @model = new Chapter() describe "Basic", -> it "should have a name by default", -> expect(@model.get("name")).toEqual("") it "should have an asset_path by default", -> expect(@model.get("asset_path")).toEqual("") it "should have an order by default", -> expect(@model.get("order")).toEqual(1) it "should be empty by default", -> expect(@model.isEmpty()).toBeTruthy() describe "Validation", -> it "requires a name", -> model = new Chapter({name: "", asset_path: "a.pdf"}) expect(model.isValid()).toBeFalsy() it "requires an asset_path", -> model = new Chapter({name: "a", asset_path: ""}) expect(model.isValid()).toBeFalsy() it "can pass validation", -> model = new Chapter({name: "a", asset_path: "a.pdf"}) expect(model.isValid()).toBeTruthy() describe "Chapter collection", -> beforeEach -> @collection = new ChapterSet() it "is empty by default", -> expect(@collection.isEmpty()).toBeTruthy() it "is empty if all chapters are empty", -> @collection.add([{}, {}, {}]) expect(@collection.isEmpty()).toBeTruthy() it "is not empty if a chapter is not empty", -> @collection.add([{}, {name: "full"}, {}]) expect(@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)