entangled 0.0.22 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +9 -6
- data/bower.json +1 -1
- data/entangled.js +1 -1
- data/lib/entangled/version.rb +1 -1
- data/spec/dummy/app/controllers/lists_controller.rb +7 -0
- data/spec/dummy/app/models/list.rb +2 -0
- data/spec/dummy/db/migrate/20150316034305_drop_messages.rb +13 -0
- data/spec/dummy/db/schema.rb +1 -7
- data/spec/dummy/public/app/app.js +1 -9
- data/spec/dummy/public/app/entangled/entangled.js +2 -0
- data/spec/dummy/public/app/services/list.js +3 -3
- data/spec/dummy/public/index.html +0 -3
- data/spec/dummy/public/test/services/entangled_test.js +263 -0
- data/spec/models/list_spec.rb +107 -1
- metadata +6 -22
- data/spec/dummy/app/controllers/messages_controller.rb +0 -41
- data/spec/dummy/public/app/controllers/message.js +0 -15
- data/spec/dummy/public/app/controllers/messages.js +0 -23
- data/spec/dummy/public/app/services/message.js +0 -7
- data/spec/dummy/public/test/controllers/lists_test.js +0 -87
- data/spec/dummy/public/test/controllers/messages_test.js +0 -249
- data/spec/dummy/public/views/messages/index.html +0 -13
- data/spec/dummy/public/views/messages/show.html +0 -8
- data/spec/models/message_spec.rb +0 -135
- data/spec/routing/messages_routing_spec.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7c388678aa588a1f547b713feb70dbd9f5aaa44
|
4
|
+
data.tar.gz: 5c4baa78c2e13abb9fdce0aabbd132698a474af4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a740b57b3679899c1c3bde3d2b969f00a5457f826af461626119fdb4083a08eba5c5115b433fc8c243736a00a6c7c074fa9b8c8673c561fd2cf6c18cef72c134
|
7
|
+
data.tar.gz: 17eb36090addf15cc12ea4a9c346dcb70411ac7273ce613ebfcf08143f9d47c15d0ee02ee8c1185a5b3200febabc2bb8fb13ac17538d205bb4a0b06daa0645e3
|
data/README.md
CHANGED
@@ -207,6 +207,8 @@ The Entangled service comes with these functions:
|
|
207
207
|
- `$update(params, callback)`
|
208
208
|
- `$destroy(callback)`
|
209
209
|
|
210
|
+
They're just like class and instance methods in Active Record.
|
211
|
+
|
210
212
|
In your controller, you could then inject that `Message` service and use it like so:
|
211
213
|
|
212
214
|
```javascript
|
@@ -411,14 +413,14 @@ The gem relies heavily on convention over configuration and currently only works
|
|
411
413
|
## Development Priorities
|
412
414
|
The following features are to be implemented next:
|
413
415
|
|
414
|
-
- Support more than one belongs_to association in back end
|
415
|
-
- Support
|
416
|
-
- Support deeply nested belongs_to
|
417
|
-
- Support has_one association in back end and front end
|
416
|
+
- Support more than one `belongs_to` association in back end
|
417
|
+
- Support `belongsTo` in front end
|
418
|
+
- Support deeply nested `belongs_to`, e.g. `Parent > Child > Grandchild`
|
419
|
+
- Support `has_one` association in back end and front end
|
418
420
|
- Add offline capabilities
|
419
421
|
- Add authentication - with JWT?
|
420
422
|
- On Heroku, tasks are always in different order depending on which ones are checked off and not
|
421
|
-
- Add
|
423
|
+
- Add `$onChange` function to objects - or could a simple $watch and $watchCollection suffice?
|
422
424
|
- Add diagram on how it works to Readme
|
423
425
|
- Check if Rails 4.0.0 supported too
|
424
426
|
- GNU instead of MIT? Or something else? How to switch?
|
@@ -426,7 +428,8 @@ The following features are to be implemented next:
|
|
426
428
|
- Handle errors gracefully (e.g. finding a non-existent id, etc, authorization error in the back end, timeouts, etc)
|
427
429
|
- Test controllers (see https://github.com/ngauthier/tubesock/issues/41)
|
428
430
|
- Freeze destroyed object
|
429
|
-
- Set
|
431
|
+
- Set `$persisted()` to false on a destroyed object
|
432
|
+
- Add `.destroyAll()` function to `Resources`
|
430
433
|
|
431
434
|
## Contributing
|
432
435
|
1. [Fork it](https://github.com/dchacke/entangled/fork) - you will notice that the repo comes with a back end and a front end part to test both parts of the gem
|
data/bower.json
CHANGED
data/entangled.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
angular.module("entangled",[]).factory("Entangled",function(){var e=function(e,t,r){for(var i in e)e.hasOwnProperty(i)&&(this[i]=e[i]);this.webSocketUrl=t,r&&(this[r]=function(){return new s(this.webSocketUrl+"/"+this.id+"/"+r)})};e.prototype.$save=function(e){if(this.id){var t=new WebSocket(this.webSocketUrl+"/"+this.id+"/update");t.onopen=function(){t.send(JSON.stringify(this))}.bind(this),t.onmessage=function(t){if(t.data){var r=JSON.parse(t.data);if(r.resource)for(key in r.resource)this[key]=r.resource[key]}this[this.hasMany]=new s(this.webSocketUrl+"/"+this.id+"/"+this.hasMany),e&&e(this)}.bind(this)}else{var t=new WebSocket(this.webSocketUrl+"/create");t.onopen=function(){t.send(JSON.stringify(this))}.bind(this),t.onmessage=function(t){if(t.data){var s=JSON.parse(t.data);if(s.resource)for(key in s.resource)this[key]=s.resource[key]}e&&e(this)}.bind(this)}},e.prototype.$update=function(e,t){for(var s in e)e.hasOwnProperty(s)&&(this[s]=e[s]);this.$save(t)},e.prototype.$destroy=function(e){var t=new WebSocket(this.webSocketUrl+"/"+this.id+"/destroy");t.onopen=function(){t.send(null)},t.onmessage=function(t){if(t.data){var s=JSON.parse(t.data);if(s.resource)for(key in s.resource)this[key]=s.resource[key]}e&&e(this)}.bind(this)},e.prototype.$valid=function(){return!(this.errors&&Object.keys(this.errors).length)},e.prototype.$invalid=function(){return!this.$valid()},e.prototype.$persisted=function(){return!!this.id};var t=function(t,s,r){this.all=[];for(var i=0;i<t.length;i++){var o=new e(t[i],s,r);this.all.push(o)}},s=function(e){this.webSocketUrl=e};return s.prototype.hasMany=function(e){this.hasMany=e},s.prototype["new"]=function(t){return new e(t,this.webSocketUrl,this.hasMany)},s.prototype.all=function(s){var r=new WebSocket(this.webSocketUrl);r.onmessage=function(i){if(i.data.length){var o=JSON.parse(i.data);if(o.resources)this.resources=new t(o.resources,r.url,this.hasMany);else if(o.action)if("create"===o.action)this.resources.all.push(new e(o.resource,r.url,this.hasMany));else if("update"===o.action){for(var n,a=0;a<this.resources.all.length;a++)this.resources.all[a].id===o.resource.id&&(n=a);this.resources.all[n]=new e(o.resource,r.url,this.hasMany)}else if("destroy"===o.action){for(var n,a=0;a<this.resources.all.length;a++)this.resources.all[a].id===o.resource.id&&(n=a);this.resources.all.splice(n,1)}else console.log("Something else other than CRUD happened..."),console.log(o)}s(this.resources.all)}.bind(this)},s.prototype.create=function(e,t){var s=this["new"](e);s.$save(t)},s.prototype.find=function(t,s){var r=this.webSocketUrl,i=new WebSocket(r+"/"+t);i.onmessage=function(t){if(t.data.length){var i=JSON.parse(t.data);i.resource&&!i.action?this.resource=new e(i.resource,r,this.hasMany):i.action?"update"===i.action?this.resource=new e(i.resource,r,this.hasMany):"destroy"===i.action&&(this.resource=void 0):(console.log("Something else other than CRUD happened..."),console.log(i))}s(this.resource)}.bind(this)},s});
|
1
|
+
angular.module("entangled",[]).factory("Entangled",function(){var e=function(e,t,r){for(var i in e)e.hasOwnProperty(i)&&(this[i]=e[i]);this.webSocketUrl=t,r&&(this[r]=function(){return new s(this.webSocketUrl+"/"+this.id+"/"+r)})};e.prototype.$save=function(e){if(this.id){var t=new WebSocket(this.webSocketUrl+"/"+this.id+"/update");t.onopen=function(){t.send(JSON.stringify(this))}.bind(this),t.onmessage=function(t){if(t.data){var r=JSON.parse(t.data);if(r.resource)for(key in r.resource)this[key]=r.resource[key]}this[this.hasMany]=new s(this.webSocketUrl+"/"+this.id+"/"+this.hasMany),e&&e(this)}.bind(this)}else{var t=new WebSocket(this.webSocketUrl+"/create");t.onopen=function(){t.send(JSON.stringify(this))}.bind(this),t.onmessage=function(t){if(t.data){var s=JSON.parse(t.data);if(s.resource)for(key in s.resource)this[key]=s.resource[key]}e&&e(this)}.bind(this)}},e.prototype.$update=function(e,t){for(var s in e)e.hasOwnProperty(s)&&(this[s]=e[s]);this.$save(t)},e.prototype.$destroy=function(e){var t=new WebSocket(this.webSocketUrl+"/"+this.id+"/destroy");t.onopen=function(){t.send(null)},t.onmessage=function(t){if(t.data){var s=JSON.parse(t.data);if(s.resource)for(key in s.resource)this[key]=s.resource[key]}e&&e(this)}.bind(this)},e.prototype.$valid=function(){return!(this.errors&&Object.keys(this.errors).length)},e.prototype.$invalid=function(){return!this.$valid()},e.prototype.$persisted=function(){return!!this.id};var t=function(t,s,r){this.all=[];for(var i=0;i<t.length;i++){var o=new e(t[i],s,r);this.all.push(o)}},s=function(e){this.className="Entangled",this.webSocketUrl=e};return s.prototype.hasMany=function(e){this.hasMany=e},s.prototype["new"]=function(t){return new e(t,this.webSocketUrl,this.hasMany)},s.prototype.all=function(s){var r=new WebSocket(this.webSocketUrl);r.onmessage=function(i){if(i.data.length){var o=JSON.parse(i.data);if(o.resources)this.resources=new t(o.resources,r.url,this.hasMany);else if(o.action)if("create"===o.action)this.resources.all.push(new e(o.resource,r.url,this.hasMany));else if("update"===o.action){for(var n,a=0;a<this.resources.all.length;a++)this.resources.all[a].id===o.resource.id&&(n=a);this.resources.all[n]=new e(o.resource,r.url,this.hasMany)}else if("destroy"===o.action){for(var n,a=0;a<this.resources.all.length;a++)this.resources.all[a].id===o.resource.id&&(n=a);this.resources.all.splice(n,1)}else console.log("Something else other than CRUD happened..."),console.log(o)}s(this.resources.all)}.bind(this)},s.prototype.create=function(e,t){var s=this["new"](e);s.$save(t)},s.prototype.find=function(t,s){var r=this.webSocketUrl,i=new WebSocket(r+"/"+t);i.onmessage=function(t){if(t.data.length){var i=JSON.parse(t.data);i.resource&&!i.action?this.resource=new e(i.resource,r,this.hasMany):i.action?"update"===i.action?this.resource=new e(i.resource,r,this.hasMany):"destroy"===i.action&&(this.resource=void 0):(console.log("Something else other than CRUD happened..."),console.log(i))}s(this.resource)}.bind(this)},s});
|
data/lib/entangled/version.rb
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
class DropMessages < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
drop_table :messages
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.down
|
7
|
+
create_table "messages", force: :cascade do |t|
|
8
|
+
t.text "body"
|
9
|
+
t.datetime "created_at", null: false
|
10
|
+
t.datetime "updated_at", null: false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
14
|
+
ActiveRecord::Schema.define(version: 20150316034305) do
|
15
15
|
|
16
16
|
create_table "barfoos", force: :cascade do |t|
|
17
17
|
t.text "body"
|
@@ -51,10 +51,4 @@ ActiveRecord::Schema.define(version: 20150314055847) do
|
|
51
51
|
t.datetime "updated_at", null: false
|
52
52
|
end
|
53
53
|
|
54
|
-
create_table "messages", force: :cascade do |t|
|
55
|
-
t.text "body"
|
56
|
-
t.datetime "created_at", null: false
|
57
|
-
t.datetime "updated_at", null: false
|
58
|
-
end
|
59
|
-
|
60
54
|
end
|
@@ -7,14 +7,6 @@ angular.module('entangledTest', [
|
|
7
7
|
|
8
8
|
.config(function($routeProvider) {
|
9
9
|
$routeProvider
|
10
|
-
.when('/', {
|
11
|
-
templateUrl: 'views/messages/index.html',
|
12
|
-
controller: 'MessagesCtrl'
|
13
|
-
})
|
14
|
-
.when('/messages/:id', {
|
15
|
-
templateUrl: 'views/messages/show.html',
|
16
|
-
controller: 'MessageCtrl'
|
17
|
-
})
|
18
10
|
.when('/lists', {
|
19
11
|
templateUrl: 'views/lists/index.html',
|
20
12
|
controller: 'ListsCtrl'
|
@@ -24,6 +16,6 @@ angular.module('entangledTest', [
|
|
24
16
|
controller: 'ListCtrl'
|
25
17
|
})
|
26
18
|
.otherwise({
|
27
|
-
redirectTo: '/'
|
19
|
+
redirectTo: '/lists'
|
28
20
|
});
|
29
21
|
})
|
@@ -179,6 +179,8 @@ angular.module('entangled', [])
|
|
179
179
|
// of the index action on the server where the
|
180
180
|
// Resources can be retrieved.
|
181
181
|
var Entangled = function(webSocketUrl) {
|
182
|
+
this.className = 'Entangled';
|
183
|
+
|
182
184
|
// Store the root URL that sockets
|
183
185
|
// will connect to
|
184
186
|
this.webSocketUrl = webSocketUrl;
|
@@ -3,7 +3,7 @@
|
|
3
3
|
angular.module('entangledTest')
|
4
4
|
|
5
5
|
.factory('List', function(Entangled) {
|
6
|
-
var
|
7
|
-
|
8
|
-
return
|
6
|
+
var List = new Entangled('ws://localhost:3000/lists');
|
7
|
+
List.hasMany('items');
|
8
|
+
return List;
|
9
9
|
});
|
@@ -10,11 +10,8 @@
|
|
10
10
|
<script src="bower_components/angular-route/angular-route.js"></script>
|
11
11
|
<script src="app/entangled/entangled.js"></script>
|
12
12
|
<script src="app/app.js"></script>
|
13
|
-
<script src="app/controllers/messages.js"></script>
|
14
|
-
<script src="app/controllers/message.js"></script>
|
15
13
|
<script src="app/controllers/lists.js"></script>
|
16
14
|
<script src="app/controllers/list.js"></script>
|
17
|
-
<script src="app/services/message.js"></script>
|
18
15
|
<script src="app/services/list.js"></script>
|
19
16
|
</body>
|
20
17
|
</html>
|
@@ -0,0 +1,263 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
describe('Entangled', function() {
|
4
|
+
beforeEach(module('entangled'));
|
5
|
+
|
6
|
+
var $injector,
|
7
|
+
Entangled,
|
8
|
+
List;
|
9
|
+
|
10
|
+
beforeEach(inject(function() {
|
11
|
+
$injector = angular.injector(['entangled']);
|
12
|
+
Entangled = $injector.get('Entangled');
|
13
|
+
|
14
|
+
List = new Entangled('ws://localhost:3000/lists');
|
15
|
+
List.hasMany('items');
|
16
|
+
}));
|
17
|
+
|
18
|
+
describe('.className', function() {
|
19
|
+
it('is "Entangled"', function() {
|
20
|
+
expect(List.className).toBe('Entangled');
|
21
|
+
});
|
22
|
+
});
|
23
|
+
|
24
|
+
describe('.new', function() {
|
25
|
+
it('instantiates a new list with given values', function() {
|
26
|
+
var list = List.new({ name: 'foo' });
|
27
|
+
expect(list).toBeDefined();
|
28
|
+
expect(list.name).toBe('foo');
|
29
|
+
});
|
30
|
+
});
|
31
|
+
|
32
|
+
describe('.all', function() {
|
33
|
+
it('fetches all lists', function(done) {
|
34
|
+
List.all(function(lists) {
|
35
|
+
expect(lists).toEqual(jasmine.any(Array));
|
36
|
+
done();
|
37
|
+
});
|
38
|
+
});
|
39
|
+
});
|
40
|
+
|
41
|
+
describe('.create', function() {
|
42
|
+
it('creates a list', function(done) {
|
43
|
+
List.create({ name: 'foo' }, function(list) {
|
44
|
+
expect(list.id).toBeDefined();
|
45
|
+
expect(list.created_at).toBeDefined();
|
46
|
+
done();
|
47
|
+
});
|
48
|
+
});
|
49
|
+
|
50
|
+
it('receives validation messages', function(done) {
|
51
|
+
// Leave out name, causing model validations
|
52
|
+
// in ActiveRecord to fail
|
53
|
+
List.create({}, function(list) {
|
54
|
+
expect(list.errors.name.indexOf("can't be blank") > -1).toBeTruthy();
|
55
|
+
done();
|
56
|
+
});
|
57
|
+
});
|
58
|
+
});
|
59
|
+
|
60
|
+
describe('.find', function() {
|
61
|
+
it('finds a list', function(done) {
|
62
|
+
List.create({ name: 'foo' }, function(list) {
|
63
|
+
List.find(list.id, function(list) {
|
64
|
+
expect(list.id).toBeDefined();
|
65
|
+
expect(list.created_at).toBeDefined();
|
66
|
+
done();
|
67
|
+
});
|
68
|
+
});
|
69
|
+
});
|
70
|
+
});
|
71
|
+
|
72
|
+
describe('#$save', function() {
|
73
|
+
describe('new record', function() {
|
74
|
+
it('saves a new list', function(done) {
|
75
|
+
var list = List.new({ name: 'foo' });
|
76
|
+
|
77
|
+
list.$save(function() {
|
78
|
+
expect(list.id).toBeDefined();
|
79
|
+
expect(list.created_at).toBeDefined();
|
80
|
+
done();
|
81
|
+
});
|
82
|
+
});
|
83
|
+
|
84
|
+
it('receives validation messages', function(done) {
|
85
|
+
// Leave out name, causing model validations
|
86
|
+
// in ActiveRecord to fail
|
87
|
+
var list = List.new();
|
88
|
+
|
89
|
+
list.$save(function() {
|
90
|
+
expect(list.errors.name.indexOf("can't be blank") > -1).toBeTruthy();
|
91
|
+
done();
|
92
|
+
});
|
93
|
+
});
|
94
|
+
});
|
95
|
+
|
96
|
+
describe('existing record', function() {
|
97
|
+
it('updates an existing list', function(done) {
|
98
|
+
List.create({ name: 'foo' }, function(list) {
|
99
|
+
list.name = 'new name';
|
100
|
+
var oldUpdatedAt = list.updated_at;
|
101
|
+
|
102
|
+
list.$save(function() {
|
103
|
+
expect(list.name).toBe('new name');
|
104
|
+
expect(list.updated_at).not.toEqual(oldUpdatedAt);
|
105
|
+
done();
|
106
|
+
});
|
107
|
+
});
|
108
|
+
});
|
109
|
+
|
110
|
+
it('receives validation messages', function(done) {
|
111
|
+
List.create({ name: 'foo' }, function(list) {
|
112
|
+
// Make invalid by setting the name to an
|
113
|
+
// empty string, causing model validations
|
114
|
+
// in ActiveRecord to fail
|
115
|
+
list.name = '';
|
116
|
+
var oldUpdatedAt = list.updated_at;
|
117
|
+
|
118
|
+
list.$save(function() {
|
119
|
+
// Assert that the list was not updated
|
120
|
+
// by the server
|
121
|
+
expect(list.updated_at).toBe(oldUpdatedAt);
|
122
|
+
expect(list.errors.name.indexOf("can't be blank") > -1).toBeTruthy();
|
123
|
+
done();
|
124
|
+
});
|
125
|
+
});
|
126
|
+
});
|
127
|
+
});
|
128
|
+
});
|
129
|
+
|
130
|
+
describe('#$update', function() {
|
131
|
+
it('updates a list in place', function(done) {
|
132
|
+
List.create({ name: 'foo' }, function(list) {
|
133
|
+
var oldUpdatedAt = list.updated_at;
|
134
|
+
|
135
|
+
list.$update({ name: 'new name' }, function() {
|
136
|
+
expect(list.name).toBe('new name');
|
137
|
+
expect(list.updated_at).not.toEqual(oldUpdatedAt);
|
138
|
+
done();
|
139
|
+
});
|
140
|
+
});
|
141
|
+
});
|
142
|
+
|
143
|
+
it('receives validation messages', function(done) {
|
144
|
+
List.create({ name: 'foo' }, function(list) {
|
145
|
+
var oldUpdatedAt = list.updated_at;
|
146
|
+
|
147
|
+
// Make invalid by setting the name to an
|
148
|
+
// empty string, causing model validations
|
149
|
+
// in ActiveRecord to fail
|
150
|
+
list.$update({ name: '' }, function() {
|
151
|
+
// Assert that the list was not updated
|
152
|
+
// by the server
|
153
|
+
expect(list.updated_at).toBe(oldUpdatedAt);
|
154
|
+
expect(list.errors.name.indexOf("can't be blank") > -1).toBeTruthy();
|
155
|
+
done();
|
156
|
+
});
|
157
|
+
});
|
158
|
+
});
|
159
|
+
});
|
160
|
+
|
161
|
+
describe('#$destroy', function() {
|
162
|
+
it('destroys a list', function(done) {
|
163
|
+
List.create({ name: 'foo' }, function(list) {
|
164
|
+
list.$destroy(function() {
|
165
|
+
// If successfully destroyed, it won't be
|
166
|
+
// included in the collection of all records
|
167
|
+
// anymore
|
168
|
+
List.all(function(lists) {
|
169
|
+
expect(lists.indexOf(list)).toBe(-1);
|
170
|
+
done();
|
171
|
+
});
|
172
|
+
});
|
173
|
+
});
|
174
|
+
});
|
175
|
+
});
|
176
|
+
|
177
|
+
describe('#$valid', function() {
|
178
|
+
var list;
|
179
|
+
|
180
|
+
beforeEach(function() {
|
181
|
+
list = List.new();
|
182
|
+
});
|
183
|
+
|
184
|
+
describe('valid record', function() {
|
185
|
+
it('is true', function() {
|
186
|
+
list.errors = {};
|
187
|
+
expect(list.$valid()).toBeTruthy();
|
188
|
+
});
|
189
|
+
});
|
190
|
+
|
191
|
+
describe('invalid record', function() {
|
192
|
+
it('is false', function() {
|
193
|
+
list.errors = {
|
194
|
+
name: ["can't be blank"]
|
195
|
+
};
|
196
|
+
|
197
|
+
expect(list.$valid()).not.toBeTruthy();
|
198
|
+
});
|
199
|
+
});
|
200
|
+
});
|
201
|
+
|
202
|
+
describe('#$invalid', function() {
|
203
|
+
var list;
|
204
|
+
|
205
|
+
beforeEach(function() {
|
206
|
+
list = List.new();
|
207
|
+
});
|
208
|
+
|
209
|
+
describe('valid record', function() {
|
210
|
+
it('is false', function() {
|
211
|
+
list.errors = {};
|
212
|
+
expect(list.$invalid()).not.toBeTruthy();
|
213
|
+
});
|
214
|
+
});
|
215
|
+
|
216
|
+
describe('invalid record', function() {
|
217
|
+
it('is true', function() {
|
218
|
+
list.errors = {
|
219
|
+
name: ["can't be blank"]
|
220
|
+
};
|
221
|
+
|
222
|
+
expect(list.$invalid()).toBeTruthy();
|
223
|
+
});
|
224
|
+
});
|
225
|
+
});
|
226
|
+
|
227
|
+
describe('#$persisted', function() {
|
228
|
+
var list;
|
229
|
+
|
230
|
+
beforeEach(function() {
|
231
|
+
list = List.new();
|
232
|
+
});
|
233
|
+
|
234
|
+
describe('persisted record', function() {
|
235
|
+
it('is true', function() {
|
236
|
+
list.id = 1;
|
237
|
+
expect(list.$persisted()).toBeTruthy();
|
238
|
+
});
|
239
|
+
});
|
240
|
+
|
241
|
+
describe('unpersisted record', function() {
|
242
|
+
it('is false', function() {
|
243
|
+
expect(list.$persisted()).not.toBeTruthy();
|
244
|
+
});
|
245
|
+
});
|
246
|
+
});
|
247
|
+
|
248
|
+
describe('Associations', function() {
|
249
|
+
it('has many items', function(done) {
|
250
|
+
List.create({ name: 'foo' }, function(list) {
|
251
|
+
// Assert that relationship defined
|
252
|
+
expect(list.items).toBeDefined();
|
253
|
+
|
254
|
+
// Assert that relationship is also
|
255
|
+
// an instance of Entangled, meaning
|
256
|
+
// in turn that all class and instance
|
257
|
+
// methods are available on it
|
258
|
+
expect(list.items().className).toBe('Entangled');
|
259
|
+
done();
|
260
|
+
});
|
261
|
+
});
|
262
|
+
});
|
263
|
+
});
|