brainstem-js 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.pairs +21 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.tm_properties +1 -0
- data/.travis.yml +12 -0
- data/Assetfile +79 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +50 -0
- data/LICENSE.txt +22 -0
- data/README.md +143 -0
- data/Rakefile +25 -0
- data/brainstemjs.gemspec +24 -0
- data/lib/brainstem/js/engine.rb +5 -0
- data/lib/brainstem/js/version.rb +5 -0
- data/lib/brainstem/js.rb +10 -0
- data/spec/brainstem-collection-spec.coffee +141 -0
- data/spec/brainstem-model-spec.coffee +283 -0
- data/spec/brainstem-sync-spec.coffee +22 -0
- data/spec/brainstem-utils-spec.coffee +12 -0
- data/spec/brianstem-expectation-spec.coffee +209 -0
- data/spec/helpers/builders.coffee +80 -0
- data/spec/helpers/jquery-matchers.js +137 -0
- data/spec/helpers/models/post.coffee +14 -0
- data/spec/helpers/models/project.coffee +13 -0
- data/spec/helpers/models/task.coffee +14 -0
- data/spec/helpers/models/time-entry.coffee +13 -0
- data/spec/helpers/models/user.coffee +8 -0
- data/spec/helpers/spec-helper.coffee +79 -0
- data/spec/storage-manager-spec.coffee +613 -0
- data/spec/support/.DS_Store +0 -0
- data/spec/support/console-runner.js +103 -0
- data/spec/support/headless.coffee +47 -0
- data/spec/support/headless.html +60 -0
- data/spec/support/runner.html +85 -0
- data/spec/vendor/backbone-factory.js +62 -0
- data/spec/vendor/backbone.js +1571 -0
- data/spec/vendor/inflection.js +448 -0
- data/spec/vendor/jquery-1.7.js +9300 -0
- data/spec/vendor/jquery.cookie.js +47 -0
- data/spec/vendor/minispade.js +67 -0
- data/spec/vendor/sinon-1.3.4.js +3561 -0
- data/spec/vendor/underscore.js +1221 -0
- data/vendor/assets/.DS_Store +0 -0
- data/vendor/assets/javascripts/.DS_Store +0 -0
- data/vendor/assets/javascripts/brainstem/brainstem-collection.coffee +53 -0
- data/vendor/assets/javascripts/brainstem/brainstem-expectation.coffee +65 -0
- data/vendor/assets/javascripts/brainstem/brainstem-inflections.js +449 -0
- data/vendor/assets/javascripts/brainstem/brainstem-model.coffee +141 -0
- data/vendor/assets/javascripts/brainstem/brainstem-sync.coffee +76 -0
- data/vendor/assets/javascripts/brainstem/index.js +1 -0
- data/vendor/assets/javascripts/brainstem/iso8601.js +41 -0
- data/vendor/assets/javascripts/brainstem/loading-mixin.coffee +13 -0
- data/vendor/assets/javascripts/brainstem/storage-manager.coffee +275 -0
- data/vendor/assets/javascripts/brainstem/utils.coffee +35 -0
- metadata +198 -0
@@ -0,0 +1,137 @@
|
|
1
|
+
// This is Wojciech's jasmine-jquery library without the fixtures. See https://github.com/velesin/jasmine-jquery
|
2
|
+
|
3
|
+
// Copyright (c) 2010 Wojciech Zawistowski
|
4
|
+
//
|
5
|
+
// Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
// a copy of this software and associated documentation files (the
|
7
|
+
// "Software"), to deal in the Software without restriction, including
|
8
|
+
// without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
// distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
// permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
// the following conditions:
|
12
|
+
//
|
13
|
+
// The above copyright notice and this permission notice shall be
|
14
|
+
// included in all copies or substantial portions of the Software.
|
15
|
+
//
|
16
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
jasmine.JQuery = function() {};
|
25
|
+
|
26
|
+
jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
|
27
|
+
return $('<div/>').append(html).html();
|
28
|
+
};
|
29
|
+
|
30
|
+
jasmine.JQuery.elementToString = function(element) {
|
31
|
+
return $('<div />').append(element.clone()).html();
|
32
|
+
};
|
33
|
+
|
34
|
+
jasmine.JQuery.matchersClass = {};
|
35
|
+
|
36
|
+
(function(){
|
37
|
+
var jQueryMatchers = {
|
38
|
+
toHaveClass: function(className) {
|
39
|
+
return this.actual.hasClass(className);
|
40
|
+
},
|
41
|
+
|
42
|
+
toBeVisible: function() {
|
43
|
+
return this.actual.is(':visible');
|
44
|
+
},
|
45
|
+
|
46
|
+
toBeHidden: function() {
|
47
|
+
return this.actual.is(':hidden');
|
48
|
+
},
|
49
|
+
|
50
|
+
toBeSelected: function() {
|
51
|
+
return this.actual.is(':selected');
|
52
|
+
},
|
53
|
+
|
54
|
+
toBeChecked: function() {
|
55
|
+
return this.actual.is(':checked');
|
56
|
+
},
|
57
|
+
|
58
|
+
toBeEmpty: function() {
|
59
|
+
return this.actual.is(':empty');
|
60
|
+
},
|
61
|
+
|
62
|
+
toExist: function() {
|
63
|
+
return this.actual.size() > 0;
|
64
|
+
},
|
65
|
+
|
66
|
+
toHaveAttr: function(attributeName, expectedAttributeValue) {
|
67
|
+
return hasProperty(this.actual.attr(attributeName), expectedAttributeValue);
|
68
|
+
},
|
69
|
+
|
70
|
+
toHaveProp: function(attributeName, expectedAttributeValue) {
|
71
|
+
return hasProperty(this.actual.prop(attributeName), expectedAttributeValue);
|
72
|
+
},
|
73
|
+
|
74
|
+
toHaveId: function(id) {
|
75
|
+
return this.actual.attr('id') == id;
|
76
|
+
},
|
77
|
+
|
78
|
+
toHaveHtml: function(html) {
|
79
|
+
return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html);
|
80
|
+
},
|
81
|
+
|
82
|
+
toHaveText: function(text) {
|
83
|
+
return this.actual.text() == text;
|
84
|
+
},
|
85
|
+
|
86
|
+
toHaveValue: function(value) {
|
87
|
+
return this.actual.val() == value;
|
88
|
+
},
|
89
|
+
|
90
|
+
toHaveData: function(key, expectedValue) {
|
91
|
+
return hasProperty(this.actual.data(key), expectedValue);
|
92
|
+
},
|
93
|
+
|
94
|
+
toBe: function(selector) {
|
95
|
+
return this.actual.is(selector);
|
96
|
+
},
|
97
|
+
|
98
|
+
toContain: function(selector) {
|
99
|
+
return this.actual.find(selector).size() > 0;
|
100
|
+
}
|
101
|
+
};
|
102
|
+
|
103
|
+
var hasProperty = function(actualValue, expectedValue) {
|
104
|
+
if (expectedValue === undefined) {
|
105
|
+
return actualValue !== undefined;
|
106
|
+
}
|
107
|
+
return actualValue == expectedValue;
|
108
|
+
};
|
109
|
+
|
110
|
+
var bindMatcher = function(methodName) {
|
111
|
+
var builtInMatcher = jasmine.Matchers.prototype[methodName];
|
112
|
+
|
113
|
+
jasmine.JQuery.matchersClass[methodName] = function() {
|
114
|
+
if (this.actual instanceof jQuery) {
|
115
|
+
var result = jQueryMatchers[methodName].apply(this, arguments);
|
116
|
+
this.actual = jasmine.JQuery.elementToString(this.actual);
|
117
|
+
return result;
|
118
|
+
}
|
119
|
+
|
120
|
+
if (builtInMatcher) {
|
121
|
+
return builtInMatcher.apply(this, arguments);
|
122
|
+
} else {
|
123
|
+
throw ("There is no " + methodName + " method on this object. Did you forget a $ jQuery call in your expect?"); // Added to help debugging.
|
124
|
+
}
|
125
|
+
|
126
|
+
return false;
|
127
|
+
};
|
128
|
+
};
|
129
|
+
|
130
|
+
for(var methodName in jQueryMatchers) {
|
131
|
+
bindMatcher(methodName);
|
132
|
+
}
|
133
|
+
})();
|
134
|
+
|
135
|
+
beforeEach(function() {
|
136
|
+
this.addMatchers(jasmine.JQuery.matchersClass);
|
137
|
+
});
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class App.Models.Post extends Brainstem.Model
|
2
|
+
brainstemKey: "posts"
|
3
|
+
paramRoot: 'post'
|
4
|
+
url: '/api/posts'
|
5
|
+
|
6
|
+
@associations:
|
7
|
+
replies: ["posts"]
|
8
|
+
project: "projects"
|
9
|
+
task: "tasks"
|
10
|
+
user: "users"
|
11
|
+
|
12
|
+
class App.Collections.Posts extends Brainstem.Collection
|
13
|
+
model: App.Models.Post
|
14
|
+
url: '/api/posts'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class App.Models.Project extends Brainstem.Model
|
2
|
+
brainstemKey: "projects"
|
3
|
+
paramRoot: 'project'
|
4
|
+
url: '/api/projects'
|
5
|
+
|
6
|
+
@associations:
|
7
|
+
tasks: ["tasks"]
|
8
|
+
time_entries: ["time_entries"]
|
9
|
+
primary_counterpart: "users"
|
10
|
+
|
11
|
+
class App.Collections.Projects extends Brainstem.Collection
|
12
|
+
model: App.Models.Project
|
13
|
+
url: '/api/projects'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class App.Models.Task extends Brainstem.Model
|
2
|
+
brainstemKey: "tasks"
|
3
|
+
paramRoot: 'task'
|
4
|
+
url: '/api/tasks.json'
|
5
|
+
|
6
|
+
@associations:
|
7
|
+
project: "projects"
|
8
|
+
assignees: ["users"]
|
9
|
+
sub_tasks: ["tasks"]
|
10
|
+
parent: "tasks"
|
11
|
+
|
12
|
+
class App.Collections.Tasks extends Brainstem.Collection
|
13
|
+
model: App.Models.Task
|
14
|
+
url: '/api/tasks.json'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class App.Models.TimeEntry extends Brainstem.Model
|
2
|
+
brainstemKey: "time_entries"
|
3
|
+
paramRoot: 'time_entry'
|
4
|
+
url: '/api/time_entries'
|
5
|
+
|
6
|
+
@associations:
|
7
|
+
project: "projects"
|
8
|
+
task: "tasks"
|
9
|
+
user: "users"
|
10
|
+
|
11
|
+
class App.Collections.TimeEntries extends Brainstem.Collection
|
12
|
+
model: App.Models.TimeEntry
|
13
|
+
url: '/api/time_entries'
|
@@ -0,0 +1,79 @@
|
|
1
|
+
window.App ?= {}
|
2
|
+
window.App.Models ?= {}
|
3
|
+
window.App.Collections ?= {}
|
4
|
+
|
5
|
+
window.resultsArray = (key, models) ->
|
6
|
+
_(models).map (model) -> { key: key, id: model.get("id") }
|
7
|
+
|
8
|
+
window.resultsObject = (models) ->
|
9
|
+
results = {}
|
10
|
+
for model in models
|
11
|
+
results[model.id] = model
|
12
|
+
results
|
13
|
+
|
14
|
+
window.convertTopLevelKeysToObjects = (data) ->
|
15
|
+
for key in _(data).keys()
|
16
|
+
continue if key in ["count", "results"]
|
17
|
+
if data[key] instanceof Array
|
18
|
+
data[key] = _(data[key]).reduce(((memo, item) -> memo[item.id] = item; memo ), {})
|
19
|
+
|
20
|
+
window.respondWith = (server, url, options) ->
|
21
|
+
if options.resultsFrom?
|
22
|
+
data = $.extend {}, options.data, results: resultsArray(options.resultsFrom, options.data[options.resultsFrom])
|
23
|
+
else
|
24
|
+
data = options.data
|
25
|
+
convertTopLevelKeysToObjects data
|
26
|
+
server.respondWith options.method || "GET",
|
27
|
+
url, [ options.status || 200,
|
28
|
+
{"Content-Type": options.content_type || "application/json"},
|
29
|
+
JSON.stringify(data) ]
|
30
|
+
|
31
|
+
beforeEach ->
|
32
|
+
# Disable jQuery animations.
|
33
|
+
$.fx.off = true
|
34
|
+
|
35
|
+
# Basic page fixture
|
36
|
+
$('#jasmine_content').html("<div id='wrapper'></div><div id='overlays'></div><div id='side-nav'></div><div id='main-view'></div></div>")
|
37
|
+
|
38
|
+
# Setup a new base.
|
39
|
+
window.base = {}
|
40
|
+
window.base.data = new Brainstem.StorageManager()
|
41
|
+
window.base.data.addCollection 'time_entries', App.Collections.TimeEntries
|
42
|
+
window.base.data.addCollection 'posts', App.Collections.Posts
|
43
|
+
window.base.data.addCollection 'tasks', App.Collections.Tasks
|
44
|
+
window.base.data.addCollection 'projects', App.Collections.Projects
|
45
|
+
window.base.data.addCollection 'users', App.Collections.Users
|
46
|
+
|
47
|
+
|
48
|
+
# Define builders
|
49
|
+
spec.defineBuilders()
|
50
|
+
|
51
|
+
# Mock out all Ajax requests.
|
52
|
+
window.server = sinon.fakeServer.create()
|
53
|
+
sinon.log = -> console.log arguments
|
54
|
+
|
55
|
+
# Requests for Backbone.history.getFragment() will always return the contents of spec.fragment.
|
56
|
+
Backbone.history ||= new Backbone.History
|
57
|
+
spyOn(Backbone.history, 'getFragment').andCallFake -> window.spec.fragment
|
58
|
+
window.spec.fragment = "mock/path"
|
59
|
+
|
60
|
+
# Prevent any actual navigation.
|
61
|
+
spyOn Backbone.History.prototype, 'start'
|
62
|
+
spyOn Backbone.History.prototype, 'navigate'
|
63
|
+
|
64
|
+
# Use Jasmine's mock clock. You can make time pass with jasmine.Clock.tick(N).
|
65
|
+
jasmine.Clock.useMock()
|
66
|
+
|
67
|
+
afterEach ->
|
68
|
+
window.clearLiveEventBindings()
|
69
|
+
window.server.restore()
|
70
|
+
$('#jasmine_content').html("")
|
71
|
+
jasmine.Clock.reset()
|
72
|
+
|
73
|
+
window.clearLiveEventBindings = ->
|
74
|
+
events = jQuery.data document, "events"
|
75
|
+
for key, value of events
|
76
|
+
delete events[key]
|
77
|
+
|
78
|
+
window.context = describe
|
79
|
+
window.xcontext = xdescribe
|