I've just started using Jasmine with maven. I have Jasmine working, but for some reason it cannot find my Backbone models. I have the JavaScript src directory pointing to the folder containing my Backbone.js models. In my JavaScript test directory I have a simple test as such:
describe('ToDo Model',function()
{
it('Test',function() {
var todo = new ToDo();
});
});
But I keep getting ToDo is not defined. Do I have to write my tests inside of the my backbone model files or anything? Thanks.
ToDo has to be in the global namespace as well. Try typing this in your Chrome/Firefox console:
window.ToDo
If it returns undefined, then that's the problem!
It's usually a good practice to define a global namespace for your app, for example:
window.Application = {
Models: {},
Views: {},
Collections: {}
}
// etc.
Then, I like to define models like this:
(function (Models) {
Models.ToDo = Backbone.Models.extend({
// etc...
});
})(Application.Models);
The namespacing here isn't necessary, but seeing Models right at the top of the file is a nice visual cue, I think.
Related
I am working on converting part of a large Backbone application to use Typescript. Some of the core js files have been converted to Typescript and are referenced by other non-TS js files.
Before we converted our requirejs modules would be of the form:
View.js
define([backbone, deps...], function (backbone, deps...) {
return backbone.View.extend({
render: function () {...}
});
});
Which in the consuming code we could do:
define([View, ...], function (View,....) {
var view = new View({...});
view.render();
});
Using Typescript external modules and exports I can compile a file containing a Typescript class to AMD but the code generated sets a property on an exports object as the results which means consuming code looks like this now, given the file name is View.js:
var view = new View.View();
This is annoying and also means we can't maintain backward compatibility with the legacy non-TS code without changes (though minor). Is there anyway to get around this?
EDIT:
Relevant generated code (the define callback)
function (require, exports) {
var Backbone = require('backbone');
var View = (function (_super) {
__extends(View, _super);
function View(options) {
_super.call(this, options);
}
})(Backbone.View);
exports.View = View;
}
The aim is to have some core components in typescript so that we can use TS going forward, and have other older libraries require the completed js components.
I am currently developing a web application where we are using the Model View Controller method for organizing our information and code. In our case we are combining the View and Controller into one Javascript file and the Model is separate.
My question comes here. I've got prototype objects in my model, but I want to instantiate instances of these objects in my viewcontroller Javascript file. How do I get them talking to each other?
There are some ways to achieve that. Today, the simplest one would be:
<script src='model.js'></script>
<script src='view-controller.js'></script>
So, since your model.js will be loaded first, you can use it inside the view/controller.
Another way is by using modules. The most used today is RequireJS. E.g:
require(['model'], function(model) {
// This function is called when model.js is loaded.
// If model.js calls define(), then this function is not fired until
// model's dependencies have loaded, and the model argument will hold
// the module value for model.js.
});
ECMAScript 6 (the next version of Javascript), will have native modules, so you'll be able to do:
import * as model from './model'
var x = model.variable; // etc
You might also want to look into using Browserify if you are familiar with Node and RequireJS as you an also use NPM modules in the front-end.
http://browserify.org/
Browserify allows you to export your JS code from one file and require it in another (simplified idea).
file 1: myfunc.js
var myFunc = function(){
console.log("I'm an exported function that's in another file");
};
module.exports = myFunc;
file 2: app.js
var myFunc = require('./myfunc.js');
myFunc(): // logs "I'm an exported function that's in another file"
Pretty straightforward question. Currently, what I do when I need to access objects' methods throughout most of the application, I do this in app.js
Ext.define('Utils', {
statics: {
myMethod: function() {
return 'myResult';
}
}
});
This works, but when I build the application, I get a warning about a circular reference (app.js of course needs all the other controller classes, but then said classes refer back to app.js).
I thought of using a package including a .js file that has all the objects/methods, but sometimes, within these methods I'll need access to the Ext namespace so that won't work.
Is there any better way to do this ?
Thanks!
You should not define the class Utils inside app.js. Each Ext.define statement should be in it's own file. Also the classname should be prefixed with your app name.
Ext.define('MyApp.Utils', {
statics: {
myMethod: function() {
return 'myResult';
}
}
});
should therefore be found in the file app/Utils.js. When compiling your sources into a compiled app.js, Sencha Cmd will take care of the proper ordering in the final file. The requires and uses directives give you enough flexibility to define any dependences between your classes.
Read all the docs about MVC to get a clear understanding.
I'm using Rails 3.2.9. When I add CoffeeScript code to a .js.coffee file in the /app/assets/javascripts directory, I get the resulting JavaScript in all of my webpages. The problem is all the JavaScript is wrapped in:
(function() {
// my code
}).call(this);
So any methods I define are not visible in any other CoffeeScript code I write in other files. What's the proper way to write a set of reusable CoffeeScript classes and methods with Rails?
The simplest thing to do is to namespace all your classes. If your application is called "app" then in your initialization code before anything else happens:
// Set up the namespace.
window.app = { }
and then in all your .coffee files:
class app.Pancakes
#...
Then you'd have a global namespace and you'd reference everything through that namespace:
pancakes = new app.Pancakes
Similarly for simple functions:
app.where_is = (pancakes, house) -> ...
# And elsewhere...
x = app.where_is(...)
There are various ways of setting up and partially hiding the namespace but they're all variations on the above and simple namespacing plays nicely with the Rails asset pipeline.
Also, you can define classes within the coffeescript files like this:
class this.Person
constructor: (attr = {}) ->
...
In that way, the definitions are attached to the global namespace.
I have a model which looks like this:
//myModel.js
define([], function () {
var MyModel = Backbone.Model.extend({
// my code
});
return MyModel
});
Then If I want to write a spec for this model how should I load the model using requireJs?
I did try the following:
//myModel.spec.js
define([
"js/models/myModel",
], function (MyModel) {
describe("My model", function()
{
beforeEach(function ()
{
this.myModel = new MyModel({
name: "my title"
});
});
});
});
Is this the right way?
Yes, this is correct. The great thing about using RequireJS for testing is that you're forced to declare all your test dependencies in your define block. By definition, a unit test should only be testing one thing. So if you have multiple dependencies in one test, it's a code smell that you're not doing real "unit testing" at all.
Ideally, the only dependency should be the file which is under test. If that file has any dependencies, itself, such as server-side services, or complex asynchronous APIS, you can use stubs and mocks to simulate them. Check out SinonJS for a great stubbing/mocking library.