angularjs-rails-resource 1.0.0.pre.2 → 1.0.0.pre.3
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/.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
|
+
});
|