brainstem-js 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +8 -0
  2. data/.pairs +21 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.tm_properties +1 -0
  6. data/.travis.yml +12 -0
  7. data/Assetfile +79 -0
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +50 -0
  10. data/LICENSE.txt +22 -0
  11. data/README.md +143 -0
  12. data/Rakefile +25 -0
  13. data/brainstemjs.gemspec +24 -0
  14. data/lib/brainstem/js/engine.rb +5 -0
  15. data/lib/brainstem/js/version.rb +5 -0
  16. data/lib/brainstem/js.rb +10 -0
  17. data/spec/brainstem-collection-spec.coffee +141 -0
  18. data/spec/brainstem-model-spec.coffee +283 -0
  19. data/spec/brainstem-sync-spec.coffee +22 -0
  20. data/spec/brainstem-utils-spec.coffee +12 -0
  21. data/spec/brianstem-expectation-spec.coffee +209 -0
  22. data/spec/helpers/builders.coffee +80 -0
  23. data/spec/helpers/jquery-matchers.js +137 -0
  24. data/spec/helpers/models/post.coffee +14 -0
  25. data/spec/helpers/models/project.coffee +13 -0
  26. data/spec/helpers/models/task.coffee +14 -0
  27. data/spec/helpers/models/time-entry.coffee +13 -0
  28. data/spec/helpers/models/user.coffee +8 -0
  29. data/spec/helpers/spec-helper.coffee +79 -0
  30. data/spec/storage-manager-spec.coffee +613 -0
  31. data/spec/support/.DS_Store +0 -0
  32. data/spec/support/console-runner.js +103 -0
  33. data/spec/support/headless.coffee +47 -0
  34. data/spec/support/headless.html +60 -0
  35. data/spec/support/runner.html +85 -0
  36. data/spec/vendor/backbone-factory.js +62 -0
  37. data/spec/vendor/backbone.js +1571 -0
  38. data/spec/vendor/inflection.js +448 -0
  39. data/spec/vendor/jquery-1.7.js +9300 -0
  40. data/spec/vendor/jquery.cookie.js +47 -0
  41. data/spec/vendor/minispade.js +67 -0
  42. data/spec/vendor/sinon-1.3.4.js +3561 -0
  43. data/spec/vendor/underscore.js +1221 -0
  44. data/vendor/assets/.DS_Store +0 -0
  45. data/vendor/assets/javascripts/.DS_Store +0 -0
  46. data/vendor/assets/javascripts/brainstem/brainstem-collection.coffee +53 -0
  47. data/vendor/assets/javascripts/brainstem/brainstem-expectation.coffee +65 -0
  48. data/vendor/assets/javascripts/brainstem/brainstem-inflections.js +449 -0
  49. data/vendor/assets/javascripts/brainstem/brainstem-model.coffee +141 -0
  50. data/vendor/assets/javascripts/brainstem/brainstem-sync.coffee +76 -0
  51. data/vendor/assets/javascripts/brainstem/index.js +1 -0
  52. data/vendor/assets/javascripts/brainstem/iso8601.js +41 -0
  53. data/vendor/assets/javascripts/brainstem/loading-mixin.coffee +13 -0
  54. data/vendor/assets/javascripts/brainstem/storage-manager.coffee +275 -0
  55. data/vendor/assets/javascripts/brainstem/utils.coffee +35 -0
  56. 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,8 @@
1
+ class App.Models.User extends Brainstem.Model
2
+ brainstemKey: "users"
3
+ paramRoot: 'user'
4
+ url: "/api/users"
5
+
6
+ class App.Collections.Users extends Brainstem.Collection
7
+ model: App.Models.User
8
+ url: "/api/users"
@@ -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