Skip to content

Instantly share code, notes, and snippets.

@ryan-roemer
Last active August 29, 2015 13:58
Show Gist options
  • Save ryan-roemer/9941465 to your computer and use it in GitHub Desktop.
Save ryan-roemer/9941465 to your computer and use it in GitHub Desktop.
Backbone.js Training - Day 3 - AMD / Frontend Testing
/**
* Application.
*
* This file is usually the "binding" of all of the individual Backbone.js
* components into a unified whole. It is also typically *not* unit tested
* because it has side effects from just running it. So, here is the expected
* place to also do things like start Backbone.js History, do `$()` DOM
* manipulation, etc.
*/
define([
"jquery",
"backbone",
// Backbone components.
"app/models/customer",
"app/collections/customers",
"app/views/customers",
// Polyfill JSON for old browsers.
"json2",
"backbone.localStorage"
], function (
$,
Backbone,
CustomerModel,
CustomersCollection,
CustomersView
) {
"use strict";
// --------------------------------------------------------------------------
// Adjustments **just** for this demo page.
// --------------------------------------------------------------------------
// Hide the existing Notes HTML content for our skeleton application.
// This hide can be removed later, once you are using the HTML content
// in `index.html`.
$(".notes-html").hide();
// Dynamically add our element for the Backbone.js view
// (Usually done in actual HTML).
$("<div class='hello' />").appendTo($("body"));
// --------------------------------------------------------------------------
// Application Bootstrap
// --------------------------------------------------------------------------
// Actually wire up and kick everything off!
//
// **Note**: The `app.js` file is usually just comprised of **imports**
// of the individual Backbone.js components above and the below function
// on page load.
$(function () {
// Create data, and manipulate.
var customers = new CustomersCollection();
customers.reset();
var customer = new CustomerModel();
customers.add(customer);
customers.create({
firstName: "Bob",
lastName: "Smith",
email: "bob.smith@formidablelabs.com"
});
// Fire up view and render everything.
var custsView = new CustomersView({
collection: customers
});
custsView.render();
});
});
/**
* Customers collection.
* app/collections/customers.js
*/
define([
"underscore",
"backbone",
"app/models/customer",
// Patches, etc.
"backbone.localStorage"
], function (
_,
Backbone,
CustomerModel
) {
var CustomersCollection = Backbone.Collection.extend({
model: CustomerModel,
localStorage: new Backbone.LocalStorage("bb-col-demo")
});
CustomersCollection.getInstance = _.memoize(function () {
return new CustomersCollection();
});
// Use cases in other code.
// ------------------------
// var col1 = new CustomersCollection();
// var col2 = new CustomersCollection();
// console.log("col1.getInstance", col1.getInstance);
// console.log("CustomersCollection.getInstance",
// CustomersCollection.getInstance);
// console.log("col1, col2", col1 === col2); // => false
// var col3 = CustomersCollection.getInstance();
// var col4 = CustomersCollection.getInstance();
// console.log("col3, col4", col3 === col4); // => true
return CustomersCollection;
});
/**
* Customer model.
* app/models/customer.js
* app/foo-bar/hi-there.js
*/
define(["backbone"], function (Backbone) {
var CustomerModel = Backbone.Model.extend({
defaults: {
firstName: "Ryan",
lastName: "Roemer",
email: "ryan.roemer@formidablelabs.com"
}
});
return CustomerModel;
});
{{! Customer Model }}
<strong>{{firstName}} {{lastName}}</strong>
<p>Your email: {{email}}</p>
<a href="http://google.com" class="customer-ln">Customer</a>
<button class="btn btn-default btn-small customer-btn">
<span class="glyphicon glyphicon-star"></span>
</button>
<span class="customer-msg" />
{{! Customers Collection }}
<strong>Our valued customers</strong>
<ul>
</ul>
define([
"backbone",
"hbs!app/templates/customer"
], function (Backbone, customerTmpl) {
/**
* Customer (model) child view.
*/
var CustomerView = Backbone.View.extend({
tagName: "li", // Creates an `li` element for view.
template: customerTmpl,
events: {
"click .customer-btn": "logModel",
"click a.customer-ln": "logModel"
},
render: function () {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
logModel: function (ev) {
ev.preventDefault();
var $el = this.$(ev.target);
var msg = JSON.stringify(this.model.toJSON());
this.$(".customer-msg").html("<pre>" + msg + "</pre>");
window.console.log($el.attr("class"));
}
});
return CustomerView;
});
/**
* Customers (collection) parent view.
*/
define([
"backbone",
"app/views/customer",
"hbs!app/templates/customers"
], function (Backbone, CustomerView, customersTmpl) {
var CustomersView = Backbone.View.extend({
el: ".hello",
template: customersTmpl,
render: function () {
this.$el.html(this.template({}));
this.collection.each(function (cust) {
// Create view bound to element already in DOM.
var custView = new CustomerView({
model: cust
});
// Render child and append to existing list.
this.$el.find("ul").append(custView.render().$el);
}, this);
return this;
}
});
return CustomersView;
});
/**
* Test dependencies.
*
* This file lists out all of the individual spec (test) files so that they
* are run by our infrastructure.
*/
define([
"spec/hello.spec",
"spec/models/customer.spec"
]);
/**
* A simple "hello world" test file (with no app dependencies yet).
*/
define([], function () {
describe("My Test Suite", function () {
it("should be true", function () {
expect(true).toBeTruthy();
});
it("should be false", function () {
expect(false).toBeFalsy();
});
});
});
define([
"app/models/customer"
], function (CustomerModel) {
describe("app/models/customer", function () {
beforeEach(function () {
this.model = new CustomerModel();
});
it("should work with stubs", function () {
var stub = sinon.stub(this.model, "get", function () {
return "FOO";
});
expect(this.model.get("firstName")).toBe("FOO");
expect(this.model.get("lastName")).toBe("FOO");
stub.restore();
});
it("should set values", function () {
this.model.set("firstName", "Bob");
expect(this.model.get("firstName")).toBe("Bob");
expect(this.model.get("firstName")).toContain("B");
expect(this.model.get("firstName")).not.toContain("z");
this.model.set("firstName", "Brian");
expect(this.model.get("firstName")).toBe("Brian");
});
it("should have defaults", function () {
expect(this.model.get("firstName")).toBe("Ryan");
expect(this.model.get("lastName")).toBe("Roemer");
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment