Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Urigo committed Sep 29, 2015
2 parents db34d0e + 25ac967 commit ed79d04
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 3 deletions.
19 changes: 18 additions & 1 deletion .docs/angular-meteor/client/content/api/api.subscribe.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@
<td><p>Optional arguments passed to publisher function on server.</p></td>
<td><a href="" class="label type-hint type-hint-object">No</a></td>
</tr>
<tr>
<td>onStop</td>
<td><a href="" class="label type-hint type-hint-object">Object with onStop callback</a></td>
<td><p>The onStop callback is called after the returned promise is resolved. It will be called with a Meteor.Error
if the subscription fails or is terminated by the server. If the subscription is stopped by calling stop on the
subscription handle or inside the publication, onStop is called with no arguments.</p></td>
<td><a href="" class="label type-hint type-hint-object">No</a></td>
</tr>
</tbody>
</table>

Expand Down Expand Up @@ -84,14 +92,23 @@
subscriptionHandle.stop();
});

$scope.$meteorSubscribe('books').then(function(subscriptionHandle){
$scope.$meteorSubscribe('books', {onStop: notifyUser}).then(function(subscriptionHandle){
// Bind all the todos to $scope.books
$scope.books = $meteor.collection(Books);

console.log($scope.books + ' is ready');

// No need to stop the subscription, it will automatically close on scope destroy
});

////////////

function notifyUser(err) {
if (err)
alert(err.reason);
else
alert('Books subscription was stopped.');
}
}
]);
}
Expand Down
25 changes: 23 additions & 2 deletions modules/angular-meteor-subscribe.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,34 @@ angularMeteorSubscribe.service('$meteorSubscribe', ['$q',

this._subscribe = function(scope, deferred, args) {
var subscription = null;
var lastArg = args[args.length - 1];

// User supplied onStop callback
// save it for later use and remove
// from subscription arguments
if (angular.isObject(lastArg) &&
angular.isFunction(lastArg.onStop)) {
var onStop = lastArg.onStop;

args.pop();
}

args.push({
onReady: function() {
deferred.resolve(subscription);
},
onError: function(err) {
deferred.reject(err);
onStop: function(err) {
if (!deferred.promise.$$state.status) {
if (err)
deferred.reject(err);
else
deferred.reject(new Meteor.Error("Subscription Stopped",
"Subscription stopped by a call to stop method. Either by the client or by the server."));
} else if (onStop)
// After promise was resolved or rejected
// call user supplied onStop callback.
onStop.apply(this, Array.prototype.slice.call(arguments));

}
});

Expand Down
1 change: 1 addition & 0 deletions package.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ Package.onTest(function(api) {
'tests/integration/angular-meteor-camera-spec.js',
'tests/integration/angular-meteor-diff-array-spec.js',
'tests/integration/angular-meteor-get-updates-spec.js',
'tests/integration/angular-meteor-subscribe-spec.js',
'tests/integration/angular-meteor-collection-spec.js',
'tests/integration/angular-meteor-object-spec.js',
'tests/integration/angular-meteor-reactive-scope-spec.js',
Expand Down
145 changes: 145 additions & 0 deletions tests/integration/angular-meteor-subscribe-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
describe('$meteorSubscribe service', function () {
var $meteorSubscribe,
$rootScope,
$scope,
ready,
stop;

var $subscriptionHandleMock = { stop: function () {stop();} };

beforeEach(angular.mock.module('angular-meteor'));
beforeEach(angular.mock.inject(function (_$meteorSubscribe_, _$rootScope_) {
$meteorSubscribe = _$meteorSubscribe_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
}));

beforeEach(function () {
spyOn(Meteor, 'subscribe').and.callFake(function () {
stop = arguments[arguments.length - 1].onStop;
ready = arguments[arguments.length - 1].onReady;

return $subscriptionHandleMock;
});
});

describe('$scope.$meteorSubscribe', function () {

it('should call Meteor.subscribe with publication arguments and event callbacks ', function () {
$scope.$meteorSubscribe('subscription', 1, 2, 3);

expect(Meteor.subscribe)
.toHaveBeenCalledWith('subscription', 1, 2, 3, {
onReady: jasmine.any(Function),
onStop: jasmine.any(Function)
});
});

it('should return promise that is resolved when subscription is ready', function (done) {
$scope.$meteorSubscribe('subscription', 1, 2, 3)
.then(function (handle) {
expect(handle).toEqual($subscriptionHandleMock);
})
.finally(done);

ready();
$rootScope.$digest();
});

it('should return promise that is rejected with a Meteor.Error', function (done) {
var promise = $scope.$meteorSubscribe('subscription', 1, 2, 3);

promise.catch(function (err) {
if (err instanceof Meteor.Error) done();
else done.fail();
});

stop();
$rootScope.$digest();
});

});

describe('pass onStop argument', function () {

it('should call Meteor.subscribe with only subscription arguments and event callback options', function () {
$scope.$meteorSubscribe('subscription', 1, 2, 3, {onStop: function () {}});

expect(Meteor.subscribe)
.toHaveBeenCalledWith('subscription', 1, 2, 3, {
onReady: jasmine.any(Function),
onStop: jasmine.any(Function)
});
});

it('should call onStop with Meteor.Error when onStop event called for subscription that was resolved', function (done) {
var error = new Meteor.Error('Error', 'reason');

$scope.$meteorSubscribe('subscription', 1, 2, 3,
{
onStop: function (err) {
if (err === error) done();
else done.fail();
}
});

ready();
stop(error);
});

it('should call onStop when subscription is stopped', function (done) {
$scope.$meteorSubscribe('subscription', 1, 2, 3,
{
onStop: function (err) {
if (!err) done();
else done.fail();
}
});

ready();
stop();
});
});

describe('$scope destroy', function () {
var onStopSpy;

beforeEach(function () {
spyOn($subscriptionHandleMock, 'stop').and.callThrough();
onStopSpy = jasmine.createSpy('onStopSpy');
});

it('should call Meteor.subscribe stop method on $destroy of scope', function () {
$scope.$meteorSubscribe('subscription', 1, 2, 3);

$scope.$destroy();
expect($subscriptionHandleMock.stop.calls.count()).toEqual(1);
});

it('should call onStop callback after subscription is resolved', function () {
$scope.$meteorSubscribe('subscription', 1, 2, 3, {onStop: onStopSpy});

ready();
$scope.$destroy();
expect($subscriptionHandleMock.stop.calls.count()).toEqual(1);
expect(onStopSpy.calls.count()).toEqual(1);
});

it('should call onStop callback after subscription is rejected', function () {
$scope.$meteorSubscribe('subscription', 1, 2, 3, {onStop: onStopSpy});

stop();
$scope.$destroy();
expect($subscriptionHandleMock.stop.calls.count()).toEqual(1);
expect(onStopSpy.calls.count()).toEqual(1);
});

it('should not call onStop callback if subscription was not resolved', function () {
$scope.$meteorSubscribe('subscription', 1, 2, 3, {onStop: onStopSpy});

$scope.$destroy();
expect($subscriptionHandleMock.stop.calls.count()).toEqual(1);
expect(onStopSpy.calls.count()).toEqual(0);
});
})
});

0 comments on commit ed79d04

Please sign in to comment.