angularjs-rails-resource 1.0.0.pre.2 → 1.0.0.pre.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +57 -1
- data/Gruntfile.js +51 -36
- data/README.md +203 -68
- data/bower.json +2 -2
- data/changelog.js +206 -0
- data/karma.conf.js +2 -1
- data/lib/angularjs-rails-resource/version.rb +1 -1
- data/package.json +9 -3
- data/test/unit/angularjs/rails/extensions/snapshotsSpec.js +428 -0
- data/test/unit/angularjs/rails/resourceProviderSpec.js +20 -0
- data/test/unit/angularjs/rails/resourceSpec.js +173 -50
- data/vendor/assets/javascripts/angularjs/rails/resource/extensions/snapshots.js +117 -0
- data/vendor/assets/javascripts/angularjs/rails/resource/resource.js +239 -52
- data/vendor/assets/javascripts/angularjs/rails/resource/serialization.js +4 -4
- data/vendor/assets/javascripts/angularjs/rails/resource/utils/inflector.js +1 -1
- data/vendor/assets/javascripts/angularjs/rails/resource/utils/injector.js +21 -4
- data/vendor/assets/javascripts/angularjs/rails/resource/utils/url_builder.js +1 -2
- metadata +7 -6
- data/angularjs-rails-resource.js +0 -1117
- data/angularjs-rails-resource.min.js +0 -7
- data/angularjs-rails-resource.zip +0 -0
data/bower.json
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "angularjs-rails-resource",
|
3
|
-
"version": "1.0.0-pre.
|
3
|
+
"version": "1.0.0-pre.3",
|
4
4
|
"main": "angularjs-rails-resource.js",
|
5
5
|
"description": "A resource factory inspired by $resource from AngularJS",
|
6
6
|
"repository": {
|
7
7
|
"type": "git",
|
8
|
-
"url": "https://github.com/FineLinePrototyping/angularjs-rails-resource.git"
|
8
|
+
"url": "https://github.com/FineLinePrototyping/dist-angularjs-rails-resource.git"
|
9
9
|
},
|
10
10
|
"dependencies": {
|
11
11
|
"angular": "*"
|
data/changelog.js
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
// Copied from angular.js and modified to suit our needs
|
4
|
+
|
5
|
+
var child = require('child_process');
|
6
|
+
var fs = require('fs');
|
7
|
+
var util = require('util');
|
8
|
+
var q = require('qq');
|
9
|
+
|
10
|
+
var GIT_LOG_CMD = 'git log --grep="%s" -E -i --format=%s %s..HEAD';
|
11
|
+
var GIT_TAG_CMD = 'git describe --tags --abbrev=0';
|
12
|
+
|
13
|
+
var HEADER_TPL = '<a name="%s"></a>\n# %s (%s)\n\n';
|
14
|
+
var LINK_ISSUE = '[#%s](https://github.com/FineLinePrototyping/angularjs-rails-resource/issues/%s)';
|
15
|
+
var LINK_COMMIT = '[%s](https://github.com/FineLinePrototyping/angularjs-rails-resource/commit/%s)';
|
16
|
+
|
17
|
+
var EMPTY_COMPONENT = '$$';
|
18
|
+
|
19
|
+
|
20
|
+
var warn = function() {
|
21
|
+
console.log('WARNING:', util.format.apply(null, arguments));
|
22
|
+
};
|
23
|
+
|
24
|
+
|
25
|
+
var parseRawCommit = function(raw) {
|
26
|
+
if (!raw) return null;
|
27
|
+
|
28
|
+
var lines = raw.split('\n');
|
29
|
+
var msg = {}, match;
|
30
|
+
|
31
|
+
msg.hash = lines.shift();
|
32
|
+
msg.subject = lines.shift();
|
33
|
+
msg.closes = [];
|
34
|
+
msg.deprecates = [];
|
35
|
+
msg.breaks = [];
|
36
|
+
|
37
|
+
lines.forEach(function(line) {
|
38
|
+
match = line.match(/(?:Closes|Fixes)\s#(\d+)/);
|
39
|
+
if (match) msg.closes.push(parseInt(match[1]));
|
40
|
+
match = line.match(/^Deprecates:\s(.*)$/);
|
41
|
+
if (match) msg.deprecates.push(match[1]);
|
42
|
+
});
|
43
|
+
|
44
|
+
match = raw.match(/BREAKING CHANGE:([\s\S]*)/);
|
45
|
+
if (match) {
|
46
|
+
msg.breaking = match[1];
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
msg.body = lines.join('\n');
|
51
|
+
match = msg.subject.match(/^(.*)\(?(.*)\)?\:\s(.*)$/);
|
52
|
+
|
53
|
+
if (!match || !match[1] || !match[3]) {
|
54
|
+
warn('Incorrect message: %s %s', msg.hash, msg.subject);
|
55
|
+
return null;
|
56
|
+
}
|
57
|
+
|
58
|
+
msg.type = match[1].toLowerCase();
|
59
|
+
msg.component = match[2];
|
60
|
+
msg.subject = match[3];
|
61
|
+
return msg;
|
62
|
+
};
|
63
|
+
|
64
|
+
|
65
|
+
var linkToIssue = function(issue) {
|
66
|
+
return util.format(LINK_ISSUE, issue, issue);
|
67
|
+
};
|
68
|
+
|
69
|
+
|
70
|
+
var linkToCommit = function(hash) {
|
71
|
+
return util.format(LINK_COMMIT, hash.substr(0, 8), hash);
|
72
|
+
};
|
73
|
+
|
74
|
+
|
75
|
+
var currentDate = function() {
|
76
|
+
var now = new Date();
|
77
|
+
var pad = function(i) {
|
78
|
+
return ('0' + i).substr(-2);
|
79
|
+
};
|
80
|
+
|
81
|
+
return util.format('%d-%s-%s', now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate()));
|
82
|
+
};
|
83
|
+
|
84
|
+
|
85
|
+
var printSection = function(stream, title, section, printCommitLinks) {
|
86
|
+
printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks;
|
87
|
+
var components = Object.getOwnPropertyNames(section).sort();
|
88
|
+
|
89
|
+
if (!components.length) return;
|
90
|
+
|
91
|
+
stream.write(util.format('\n## %s\n\n', title));
|
92
|
+
|
93
|
+
components.forEach(function(name) {
|
94
|
+
var prefix = '-';
|
95
|
+
var nested = section[name].length > 1;
|
96
|
+
|
97
|
+
if (name !== EMPTY_COMPONENT) {
|
98
|
+
if (nested) {
|
99
|
+
stream.write(util.format('- **%s:**\n', name));
|
100
|
+
prefix = ' -';
|
101
|
+
} else {
|
102
|
+
prefix = util.format('- **%s:**', name);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
section[name].forEach(function(commit) {
|
107
|
+
if (printCommitLinks) {
|
108
|
+
stream.write(util.format('%s %s\n (%s', prefix, commit.subject, linkToCommit(commit.hash)));
|
109
|
+
if (commit.closes.length) {
|
110
|
+
stream.write(',\n ' + commit.closes.map(linkToIssue).join(', '));
|
111
|
+
}
|
112
|
+
stream.write(')\n');
|
113
|
+
} else {
|
114
|
+
stream.write(util.format('%s %s', prefix, commit.subject));
|
115
|
+
}
|
116
|
+
});
|
117
|
+
});
|
118
|
+
|
119
|
+
stream.write('\n');
|
120
|
+
};
|
121
|
+
|
122
|
+
|
123
|
+
var readGitLog = function(grep, from) {
|
124
|
+
var deferred = q.defer();
|
125
|
+
child.exec(util.format(GIT_LOG_CMD, grep, '%H%n%s%n%b%n==END==', from), function(code, stdout, stderr) {
|
126
|
+
var commits = [];
|
127
|
+
|
128
|
+
stdout.split('\n==END==\n').forEach(function(rawCommit) {
|
129
|
+
var commit = parseRawCommit(rawCommit);
|
130
|
+
if (commit) commits.push(commit);
|
131
|
+
});
|
132
|
+
|
133
|
+
deferred.resolve(commits);
|
134
|
+
});
|
135
|
+
|
136
|
+
return deferred.promise;
|
137
|
+
};
|
138
|
+
|
139
|
+
|
140
|
+
var writeChangelog = function(stream, commits, version) {
|
141
|
+
var sections = {
|
142
|
+
fix: {},
|
143
|
+
feat: {},
|
144
|
+
perf: {},
|
145
|
+
deprecate: {},
|
146
|
+
breaks: {}
|
147
|
+
};
|
148
|
+
|
149
|
+
sections.breaks[EMPTY_COMPONENT] = [];
|
150
|
+
|
151
|
+
commits.forEach(function(commit) {
|
152
|
+
var section = sections[commit.type];
|
153
|
+
var component = commit.component || EMPTY_COMPONENT;
|
154
|
+
|
155
|
+
if (section) {
|
156
|
+
section[component] = section[component] || [];
|
157
|
+
section[component].push(commit);
|
158
|
+
}
|
159
|
+
|
160
|
+
if (commit.breaking) {
|
161
|
+
sections.breaks[component] = sections.breaks[component] || [];
|
162
|
+
sections.breaks[component].push({
|
163
|
+
subject: util.format("due to %s,\n %s", linkToCommit(commit.hash), commit.breaking),
|
164
|
+
hash: commit.hash,
|
165
|
+
closes: []
|
166
|
+
});
|
167
|
+
}
|
168
|
+
});
|
169
|
+
|
170
|
+
stream.write(util.format(HEADER_TPL, version, version, currentDate()));
|
171
|
+
printSection(stream, 'Bug Fixes', sections.fix);
|
172
|
+
printSection(stream, 'Features', sections.feat);
|
173
|
+
printSection(stream, 'Deprecations', sections.deprecates);
|
174
|
+
printSection(stream, 'Breaking Changes', sections.breaks, false);
|
175
|
+
}
|
176
|
+
|
177
|
+
|
178
|
+
var getPreviousTag = function() {
|
179
|
+
var deferred = q.defer();
|
180
|
+
child.exec(GIT_TAG_CMD, function(code, stdout, stderr) {
|
181
|
+
if (code) deferred.reject('Cannot get the previous tag.');
|
182
|
+
else deferred.resolve(stdout.replace('\n', ''));
|
183
|
+
});
|
184
|
+
return deferred.promise;
|
185
|
+
};
|
186
|
+
|
187
|
+
|
188
|
+
var generate = function(version, file) {
|
189
|
+
getPreviousTag().then(function(tag) {
|
190
|
+
console.log('Reading git log since', tag);
|
191
|
+
readGitLog('^fix|^feat|^perf|^deprecate|BREAKING', tag).then(function(commits) {
|
192
|
+
console.log('Parsed', commits.length, 'commits');
|
193
|
+
console.log('Generating changelog to', file || 'stdout', '(', version, ')');
|
194
|
+
writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version);
|
195
|
+
});
|
196
|
+
});
|
197
|
+
};
|
198
|
+
|
199
|
+
|
200
|
+
// publish for testing
|
201
|
+
exports.parseRawCommit = parseRawCommit;
|
202
|
+
|
203
|
+
// hacky start if not run by jasmine :-D
|
204
|
+
if (process.argv.join('').indexOf('jasmine-node') === -1) {
|
205
|
+
generate(process.argv[2], process.argv[3]);
|
206
|
+
}
|
data/karma.conf.js
CHANGED
@@ -11,7 +11,8 @@ module.exports = function(config) {
|
|
11
11
|
'test/lib/angular/angular-loader.js',
|
12
12
|
'test/lib/angular/angular-sanitize.js',
|
13
13
|
'test/lib/angular/angular-mocks.js',
|
14
|
-
'vendor/assets/javascripts
|
14
|
+
'vendor/assets/javascripts/angularjs/rails/resource/index.js',
|
15
|
+
'vendor/assets/javascripts/angularjs/rails/resource/**/*.js',
|
15
16
|
'test/unit/**/*.js'
|
16
17
|
],
|
17
18
|
junitReporter: {
|
data/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "angularjs-rails-resource",
|
3
3
|
"description" : "A resource factory inspired by $resource from AngularJS",
|
4
|
-
"version": "1.0.0-pre.
|
4
|
+
"version": "1.0.0-pre.3",
|
5
5
|
"main" : "dist/angularjs-rails-resource.min.js",
|
6
6
|
"homepage" : "https://github.com/FineLinePrototyping/angularjs-rails-resource.git",
|
7
7
|
"author" : "",
|
@@ -19,13 +19,19 @@
|
|
19
19
|
"grunt-contrib-jshint": "~0.6.0",
|
20
20
|
"grunt-contrib-uglify": "~0.2.2",
|
21
21
|
"grunt-contrib-concat": "~0.3.0",
|
22
|
+
"grunt-contrib-copy": "~0.4.1",
|
23
|
+
"grunt-contrib-clean": "~0.5.0",
|
22
24
|
"grunt-contrib-watch": "~0.5.1",
|
23
|
-
"grunt-
|
25
|
+
"grunt-contrib-compress": "~0.5.2",
|
26
|
+
"grunt-bump": "~0.0.13",
|
24
27
|
"karma": "~0.10",
|
25
28
|
"karma-jasmine": "~0.1",
|
26
29
|
"karma-chrome-launcher": "~0.1",
|
27
30
|
"karma-phantomjs-launcher": "~0.1",
|
28
|
-
"karma-junit-reporter": "~0.1"
|
31
|
+
"karma-junit-reporter": "~0.1",
|
32
|
+
"q": "~0.9.2",
|
33
|
+
"q-io": "~1.10.6",
|
34
|
+
"qq": "~0.3.5"
|
29
35
|
},
|
30
36
|
"scripts": {
|
31
37
|
"test": "./node_modules/.bin/karma start --single-run --browsers PhantomJS"
|
@@ -0,0 +1,428 @@
|
|
1
|
+
describe('RailsResource.snapshots', function () {
|
2
|
+
'use strict';
|
3
|
+
var Book, $httpBackend, railsResourceFactory, railsSerializer;
|
4
|
+
|
5
|
+
beforeEach(function () {
|
6
|
+
module('rails')
|
7
|
+
});
|
8
|
+
|
9
|
+
beforeEach(inject(function (_$httpBackend_, _railsResourceFactory_, _railsSerializer_) {
|
10
|
+
$httpBackend = _$httpBackend_;
|
11
|
+
railsResourceFactory = _railsResourceFactory_;
|
12
|
+
railsSerializer = _railsSerializer_;
|
13
|
+
Book = railsResourceFactory({
|
14
|
+
url: '/books',
|
15
|
+
name: 'book',
|
16
|
+
extensions: ['snapshots']
|
17
|
+
});
|
18
|
+
}));
|
19
|
+
|
20
|
+
afterEach(function() {
|
21
|
+
$httpBackend.verifyNoOutstandingExpectation();
|
22
|
+
$httpBackend.verifyNoOutstandingRequest();
|
23
|
+
});
|
24
|
+
|
25
|
+
it('should store all keys', function () {
|
26
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
27
|
+
book = new Book(data);
|
28
|
+
expect(book.snapshot()).toBe(0);
|
29
|
+
|
30
|
+
expect(book.$snapshots).toBeDefined();
|
31
|
+
expect(book.$snapshots.length).toBe(1);
|
32
|
+
expect(book.$snapshots[0].$snapshots).toBeUndefined();
|
33
|
+
expect(book).toEqualData(data);
|
34
|
+
expect(book.$snapshots[0].$key).toBe('1234');
|
35
|
+
expect(book.$snapshots[0]).toEqualData(data);
|
36
|
+
});
|
37
|
+
|
38
|
+
it('should store deep copy', function () {
|
39
|
+
var book, data = {
|
40
|
+
id: 1,
|
41
|
+
$key: '1234',
|
42
|
+
name: 'The Winds of Winter',
|
43
|
+
author: {
|
44
|
+
id: 1,
|
45
|
+
name: 'George R. R. Martin'
|
46
|
+
}
|
47
|
+
};
|
48
|
+
|
49
|
+
book = new Book(data);
|
50
|
+
book.snapshot();
|
51
|
+
|
52
|
+
expect(book.$snapshots[0].author).toBeDefined();
|
53
|
+
expect(book.$snapshots[0].author.id).toBe(1);
|
54
|
+
expect(book.$snapshots[0]).toEqualData(data);
|
55
|
+
});
|
56
|
+
|
57
|
+
it('should store multiple snapshots', function () {
|
58
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
59
|
+
book = new Book(data);
|
60
|
+
expect(book.snapshot()).toBe(0);
|
61
|
+
book.$key = '1235';
|
62
|
+
expect(book.snapshot()).toBe(1);
|
63
|
+
book.$key = '1236';
|
64
|
+
expect(book.snapshot()).toBe(2);
|
65
|
+
|
66
|
+
expect(book.$snapshots).toBeDefined();
|
67
|
+
expect(book.$snapshots.length).toBe(3);
|
68
|
+
expect(book.$snapshots[0].$key).toBe('1234');
|
69
|
+
expect(book.$snapshots[1].$key).toBe('1235');
|
70
|
+
expect(book.$snapshots[2].$key).toBe('1236');
|
71
|
+
});
|
72
|
+
|
73
|
+
it('should rollback single version', function () {
|
74
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
75
|
+
book = new Book(data);
|
76
|
+
book.snapshot();
|
77
|
+
book.$key = '1235';
|
78
|
+
book.snapshot();
|
79
|
+
book.$key = '1236';
|
80
|
+
book.rollback();
|
81
|
+
|
82
|
+
expect(book.$key).toBe('1235');
|
83
|
+
expect(book.$snapshots).toBeDefined();
|
84
|
+
expect(book.$snapshots.length).toBe(1);
|
85
|
+
});
|
86
|
+
|
87
|
+
it('should rollback deep copy', function () {
|
88
|
+
var book, data = {
|
89
|
+
id: 1,
|
90
|
+
$key: '1234',
|
91
|
+
name: 'The Winds of Winter',
|
92
|
+
author: {
|
93
|
+
id: 1,
|
94
|
+
name: 'George R. R. Martin'
|
95
|
+
}
|
96
|
+
};
|
97
|
+
|
98
|
+
book = new Book(data);
|
99
|
+
book.snapshot();
|
100
|
+
book.author = {id: 2, name: 'Hugh Howey'};
|
101
|
+
book.rollback();
|
102
|
+
|
103
|
+
expect(book.author).toBeDefined();
|
104
|
+
expect(book).toEqualData(data);
|
105
|
+
|
106
|
+
book.snapshot();
|
107
|
+
book.author.name = 'Hugh Howey';
|
108
|
+
book.rollback();
|
109
|
+
|
110
|
+
expect(book.author).toBeDefined();
|
111
|
+
expect(book).toEqualData(data);
|
112
|
+
});
|
113
|
+
|
114
|
+
it('should not modify source nested object on rollback', function () {
|
115
|
+
var book, hughHoweyAuthor = {id: 2, name: 'Hugh Howey'},
|
116
|
+
data = {
|
117
|
+
id: 1,
|
118
|
+
$key: '1234',
|
119
|
+
name: 'The Winds of Winter',
|
120
|
+
author: {
|
121
|
+
id: 1,
|
122
|
+
name: 'George R. R. Martin'
|
123
|
+
}
|
124
|
+
};
|
125
|
+
|
126
|
+
book = new Book(data);
|
127
|
+
book.snapshot();
|
128
|
+
book.author = hughHoweyAuthor;
|
129
|
+
book.rollback();
|
130
|
+
|
131
|
+
expect(hughHoweyAuthor).toEqualData({id: 2, name: 'Hugh Howey'});
|
132
|
+
});
|
133
|
+
|
134
|
+
|
135
|
+
it('should allow multiple rollbacks', function () {
|
136
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
137
|
+
book = new Book(data);
|
138
|
+
book.snapshot();
|
139
|
+
book.$key = '1235';
|
140
|
+
book.snapshot();
|
141
|
+
book.$key = '1236';
|
142
|
+
book.rollback();
|
143
|
+
|
144
|
+
expect(book.$key).toBe('1235');
|
145
|
+
expect(book.$snapshots).toBeDefined();
|
146
|
+
expect(book.$snapshots.length).toBe(1);
|
147
|
+
book.rollback();
|
148
|
+
|
149
|
+
expect(book.$key).toBe('1234');
|
150
|
+
expect(book.$snapshots).toBeDefined();
|
151
|
+
expect(book.$snapshots.length).toBe(0);
|
152
|
+
});
|
153
|
+
|
154
|
+
|
155
|
+
it('should rollback specified number of versions', function () {
|
156
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
157
|
+
book = new Book(data);
|
158
|
+
book.snapshot();
|
159
|
+
book.$key = '1235';
|
160
|
+
book.snapshot();
|
161
|
+
book.$key = '1236';
|
162
|
+
book.snapshot();
|
163
|
+
book.$key = '1237';
|
164
|
+
book.rollback(2);
|
165
|
+
|
166
|
+
expect(book.$key).toBe('1235');
|
167
|
+
expect(book.$snapshots).toBeDefined();
|
168
|
+
expect(book.$snapshots.length).toBe(1);
|
169
|
+
});
|
170
|
+
|
171
|
+
it('should not change resource on rollback if no snapshots saved', function () {
|
172
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
173
|
+
book = new Book(data);
|
174
|
+
book.$key = '1235';
|
175
|
+
book.rollback();
|
176
|
+
|
177
|
+
expect(book.$key).toBe('1235');
|
178
|
+
expect(book.$snapshots).toBeDefined();
|
179
|
+
expect(book.$snapshots.length).toBe(0);
|
180
|
+
});
|
181
|
+
|
182
|
+
it('should roll back to the first snapshot for -1', function () {
|
183
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
184
|
+
book = new Book(data);
|
185
|
+
book.snapshot();
|
186
|
+
book.$key = '1235';
|
187
|
+
book.snapshot();
|
188
|
+
book.$key = '1236';
|
189
|
+
book.snapshot();
|
190
|
+
book.rollback(-1);
|
191
|
+
|
192
|
+
expect(book.$key).toBe('1234');
|
193
|
+
expect(book.$snapshots).toBeDefined();
|
194
|
+
expect(book.$snapshots.length).toBe(0);
|
195
|
+
});
|
196
|
+
|
197
|
+
it('should roll back to the first snapshot when versions exceeds available snapshots', function () {
|
198
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
199
|
+
book = new Book(data);
|
200
|
+
book.snapshot();
|
201
|
+
book.$key = '1235';
|
202
|
+
book.snapshot();
|
203
|
+
book.$key = '1236';
|
204
|
+
book.snapshot();
|
205
|
+
book.rollback(1000);
|
206
|
+
|
207
|
+
expect(book.$key).toBe('1234');
|
208
|
+
expect(book.$snapshots).toBeDefined();
|
209
|
+
expect(book.$snapshots.length).toBe(0);
|
210
|
+
});
|
211
|
+
|
212
|
+
it('should roll back to version in middle', function () {
|
213
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
214
|
+
book = new Book(data);
|
215
|
+
book.snapshot();
|
216
|
+
book.$key = '1235';
|
217
|
+
book.snapshot();
|
218
|
+
book.$key = '1236';
|
219
|
+
book.snapshot();
|
220
|
+
book.rollbackTo(1);
|
221
|
+
|
222
|
+
expect(book.$key).toBe('1235');
|
223
|
+
expect(book.$snapshots).toBeDefined();
|
224
|
+
expect(book.$snapshots.length).toBe(1);
|
225
|
+
});
|
226
|
+
|
227
|
+
it('should roll back to first version', function () {
|
228
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
229
|
+
book = new Book(data);
|
230
|
+
book.snapshot();
|
231
|
+
book.$key = '1235';
|
232
|
+
book.snapshot();
|
233
|
+
book.$key = '1236';
|
234
|
+
book.snapshot();
|
235
|
+
book.rollbackTo(0);
|
236
|
+
|
237
|
+
expect(book.$key).toBe('1234');
|
238
|
+
expect(book.$snapshots).toBeDefined();
|
239
|
+
expect(book.$snapshots.length).toBe(0);
|
240
|
+
});
|
241
|
+
|
242
|
+
it('should roll back to last version when version exceeds available versions', function () {
|
243
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
244
|
+
book = new Book(data);
|
245
|
+
book.snapshot();
|
246
|
+
book.$key = '1235';
|
247
|
+
book.snapshot();
|
248
|
+
book.$key = '1236';
|
249
|
+
book.snapshot();
|
250
|
+
book.$key = '1237';
|
251
|
+
book.rollbackTo(100);
|
252
|
+
|
253
|
+
expect(book.$key).toBe('1236');
|
254
|
+
expect(book.$snapshots).toBeDefined();
|
255
|
+
expect(book.$snapshots.length).toBe(2);
|
256
|
+
});
|
257
|
+
|
258
|
+
it('should reset snapshots on create', function () {
|
259
|
+
var book, data = {$key: '1234', name: 'The Winds of Winter'};
|
260
|
+
book = new Book(data);
|
261
|
+
book.snapshot();
|
262
|
+
book.$key = '1235';
|
263
|
+
|
264
|
+
$httpBackend.expectPOST('/books').respond(200, {book: {id: 1}});
|
265
|
+
book.save();
|
266
|
+
$httpBackend.flush();
|
267
|
+
|
268
|
+
expect(book.$key).toBe('1235');
|
269
|
+
expect(book.$snapshots).toBeDefined();
|
270
|
+
expect(book.$snapshots.length).toBe(0);
|
271
|
+
});
|
272
|
+
|
273
|
+
it('should be able to save after rollback', function () {
|
274
|
+
var book, data = {$key: '1234', name: 'The Winds of Winter'};
|
275
|
+
book = new Book(data);
|
276
|
+
book.snapshot();
|
277
|
+
book.$key = '1235';
|
278
|
+
book.rollback();
|
279
|
+
|
280
|
+
$httpBackend.expectPOST('/books').respond(200, {book: {id: 1}});
|
281
|
+
book.save();
|
282
|
+
$httpBackend.flush();
|
283
|
+
|
284
|
+
expect(book.$key).toBe('1234');
|
285
|
+
expect(book.$snapshots).toBeDefined();
|
286
|
+
expect(book.$snapshots.length).toBe(0);
|
287
|
+
});
|
288
|
+
|
289
|
+
it('should reset snapshots on update', function () {
|
290
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
291
|
+
book = new Book(data);
|
292
|
+
book.snapshot();
|
293
|
+
book.$key = '1235';
|
294
|
+
|
295
|
+
$httpBackend.expectPUT('/books/1').respond(200, {book: {id: 1}});
|
296
|
+
book.save();
|
297
|
+
$httpBackend.flush();
|
298
|
+
|
299
|
+
expect(book.$key).toBe('1235');
|
300
|
+
expect(book.$snapshots).toBeDefined();
|
301
|
+
expect(book.$snapshots.length).toBe(0);
|
302
|
+
});
|
303
|
+
|
304
|
+
it('should reset snapshots on delete', function () {
|
305
|
+
var book, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
306
|
+
book = new Book(data);
|
307
|
+
book.snapshot();
|
308
|
+
book.$key = '1235';
|
309
|
+
|
310
|
+
$httpBackend.expectDELETE('/books/1').respond(200, {book: {id: 1}});
|
311
|
+
book.delete();
|
312
|
+
$httpBackend.flush();
|
313
|
+
|
314
|
+
expect(book.$key).toBe('1235');
|
315
|
+
expect(book.$snapshots).toBeDefined();
|
316
|
+
expect(book.$snapshots.length).toBe(0);
|
317
|
+
});
|
318
|
+
|
319
|
+
it('should call rollback callback on rollback', function () {
|
320
|
+
var book, callbackCalled = false, data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
321
|
+
book = new Book(data);
|
322
|
+
book.snapshot(function () {
|
323
|
+
callbackCalled = true;
|
324
|
+
});
|
325
|
+
book.rollback();
|
326
|
+
expect(callbackCalled).toBe(true);
|
327
|
+
});
|
328
|
+
|
329
|
+
it('should call correct rollback callback on each rollback', function () {
|
330
|
+
var book, firstCallbackCalled = false, secondCallbackCalled = false,
|
331
|
+
data = {id: 1, $key: '1234', name: 'The Winds of Winter'};
|
332
|
+
book = new Book(data);
|
333
|
+
book.snapshot(function () {
|
334
|
+
firstCallbackCalled = true;
|
335
|
+
});
|
336
|
+
book.$key = '1235';
|
337
|
+
book.snapshot(function () {
|
338
|
+
secondCallbackCalled = true;
|
339
|
+
});
|
340
|
+
book.$key = '1236';
|
341
|
+
|
342
|
+
book.rollback();
|
343
|
+
expect(book.$key).toBe('1235');
|
344
|
+
expect(firstCallbackCalled).toBe(false);
|
345
|
+
expect(secondCallbackCalled).toBe(true);
|
346
|
+
|
347
|
+
book.rollback();
|
348
|
+
expect(book.$key).toBe('1234');
|
349
|
+
expect(firstCallbackCalled).toBe(true);
|
350
|
+
expect(secondCallbackCalled).toBe(true);
|
351
|
+
});
|
352
|
+
|
353
|
+
describe('serializer', function () {
|
354
|
+
beforeEach(function () {
|
355
|
+
Book.configure({
|
356
|
+
serializer: railsSerializer(function () {
|
357
|
+
this.exclude('author');
|
358
|
+
})
|
359
|
+
});
|
360
|
+
});
|
361
|
+
|
362
|
+
it('should exclude author from snapshot and rollback', function () {
|
363
|
+
var book, data = {
|
364
|
+
id: 1,
|
365
|
+
$key: '1234',
|
366
|
+
name: 'The Winds of Winter',
|
367
|
+
author: {
|
368
|
+
id: 1,
|
369
|
+
name: 'George R. R. Martin'
|
370
|
+
}
|
371
|
+
};
|
372
|
+
|
373
|
+
book = new Book(data);
|
374
|
+
book.snapshot();
|
375
|
+
book.author.name = 'George Orwell';
|
376
|
+
|
377
|
+
expect(book.$snapshots[0].author).not.toBeDefined();
|
378
|
+
expect(book.author).toEqualData({id: 1, name: 'George Orwell'});
|
379
|
+
|
380
|
+
book.rollback();
|
381
|
+
// should still be George Orwell since it wasn't snapshotted
|
382
|
+
expect(book.author).toEqualData({id: 1, name: 'George Orwell'});
|
383
|
+
});
|
384
|
+
|
385
|
+
});
|
386
|
+
|
387
|
+
describe('snapshotSerializer', function () {
|
388
|
+
beforeEach(function () {
|
389
|
+
Book.configure({
|
390
|
+
serializer: railsSerializer(function () {
|
391
|
+
this.exclude('author');
|
392
|
+
}),
|
393
|
+
snapshotSerializer: railsSerializer(function () {
|
394
|
+
this.exclude('$key');
|
395
|
+
})
|
396
|
+
});
|
397
|
+
});
|
398
|
+
|
399
|
+
it('should include author and exclude $key from snapshot and rollback', function () {
|
400
|
+
var book, data = {
|
401
|
+
id: 1,
|
402
|
+
$key: '1234',
|
403
|
+
name: 'The Winds of Winter',
|
404
|
+
author: {
|
405
|
+
id: 1,
|
406
|
+
name: 'George R. R. Martin'
|
407
|
+
}
|
408
|
+
};
|
409
|
+
|
410
|
+
book = new Book(data);
|
411
|
+
book.snapshot();
|
412
|
+
book.$key = '1235';
|
413
|
+
book.author.name = 'George Orwell';
|
414
|
+
|
415
|
+
expect(book.$snapshots[0].author).toBeDefined();
|
416
|
+
expect(book.$snapshots[0].$key).not.toBeDefined();
|
417
|
+
expect(book.$key).toBe('1235');
|
418
|
+
expect(book.author).toEqualData({id: 1, name: 'George Orwell'});
|
419
|
+
|
420
|
+
book.rollback();
|
421
|
+
// should be 1235 since it wasn't snapshotted
|
422
|
+
expect(book.$key).toBe('1235');
|
423
|
+
// should be George R. R. Martin since it was snapshotted
|
424
|
+
expect(book.author).toEqualData({id: 1, name: 'George R. R. Martin'});
|
425
|
+
});
|
426
|
+
|
427
|
+
});
|
428
|
+
});
|