[Views] Update representations on mutation (#1312)

* [Core] Log errors from topic

Log full error (including stack trace) when catching errors
from the topic service. Aids debugging of #1303 (and should
aid in future debugging of any similar issues.)

* [API] Fix identifier usage in handleMutation

To address console errors observed in the context of #1303

* [Views] Listen to mutation

Listen for mutation instead of watching modified timestamp;
more reliable due to recent API changes. Fixes #1303.

* [Views] Update spec for mct-representation

...to reflect changes for #1303
This commit is contained in:
Victor Woeltjen 2016-11-07 10:08:53 -08:00 committed by Pete Richards
parent 547696d797
commit 9578fb0cd8
4 changed files with 31 additions and 18 deletions

View File

@ -67,6 +67,7 @@ define(
listener(message); listener(message);
} catch (e) { } catch (e) {
$log.error(ERROR_PREFIX + e.message); $log.error(ERROR_PREFIX + e.message);
$log.error(e);
} }
}); });
} }

View File

@ -90,7 +90,7 @@ define(
couldRepresent = false, couldRepresent = false,
lastIdPath = [], lastIdPath = [],
lastKey, lastKey,
statusListener, mutationListener,
changeTemplate = templateLinker.link($scope, element); changeTemplate = templateLinker.link($scope, element);
// Populate scope with any capabilities indicated by the // Populate scope with any capabilities indicated by the
@ -101,7 +101,16 @@ define(
uses = ((representation || {}).uses || []), uses = ((representation || {}).uses || []),
myCounter = counter; myCounter = counter;
if (mutationListener) {
mutationListener();
mutationListener = undefined;
}
if (domainObject) { if (domainObject) {
mutationListener = domainObject
.getCapability('mutation')
.listen(refreshCapabilities);
// Update model // Update model
$scope.model = domainObject.getModel(); $scope.model = domainObject.getModel();
@ -236,17 +245,12 @@ define(
// (to a different object) // (to a different object)
$scope.$watch("domainObject", refresh); $scope.$watch("domainObject", refresh);
// Finally, also update when there is a new version of that
// same domain object; these changes should be tracked in the
// model's "modified" field, by the mutation capability.
$scope.$watch("domainObject.getModel().modified", refreshCapabilities);
// Make sure any resources allocated by representers also get // Make sure any resources allocated by representers also get
// released. // released.
$scope.$on("$destroy", destroyRepresenters); $scope.$on("$destroy", destroyRepresenters);
$scope.$on("$destroy", function () { $scope.$on("$destroy", function () {
if (statusListener) { if (mutationListener) {
statusListener(); mutationListener();
} }
}); });

View File

@ -36,7 +36,7 @@ define(
testViews, testViews,
testUrls, testUrls,
mockRepresenters, mockRepresenters,
mockStatusCapability, mockMutationCapability,
mockQ, mockQ,
mockLinker, mockLinker,
mockLog, mockLog,
@ -119,7 +119,8 @@ define(
mockChangeTemplate = jasmine.createSpy('changeTemplate'); mockChangeTemplate = jasmine.createSpy('changeTemplate');
mockLog = jasmine.createSpyObj("$log", LOG_FUNCTIONS); mockLog = jasmine.createSpyObj("$log", LOG_FUNCTIONS);
mockStatusCapability = jasmine.createSpyObj("statusCapability", ["listen"]); mockMutationCapability =
jasmine.createSpyObj("mutation", ["listen"]);
mockScope = jasmine.createSpyObj("scope", ["$watch", "$on"]); mockScope = jasmine.createSpyObj("scope", ["$watch", "$on"]);
mockElement = jasmine.createSpyObj("element", JQLITE_FUNCTIONS); mockElement = jasmine.createSpyObj("element", JQLITE_FUNCTIONS);
@ -132,7 +133,7 @@ define(
}); });
mockDomainObject.getCapability.andCallFake(function (c) { mockDomainObject.getCapability.andCallFake(function (c) {
return c === 'status' && mockStatusCapability; return c === 'mutation' && mockMutationCapability;
}); });
mctRepresentation = new MCTRepresentation( mctRepresentation = new MCTRepresentation(
@ -164,10 +165,6 @@ define(
"domainObject", "domainObject",
jasmine.any(Function) jasmine.any(Function)
); );
expect(mockScope.$watch).toHaveBeenCalledWith(
"domainObject.getModel().modified",
jasmine.any(Function)
);
}); });
it("recognizes keys for representations", function () { it("recognizes keys for representations", function () {
@ -272,10 +269,16 @@ define(
); );
mockDomainObject.getCapability.andCallFake(function (c) { mockDomainObject.getCapability.andCallFake(function (c) {
return c === 'context' && mockContext; return {
context: mockContext,
mutation: mockMutationCapability
}[c];
}); });
mockLink.getCapability.andCallFake(function (c) { mockLink.getCapability.andCallFake(function (c) {
return c === 'context' && mockContext2; return {
context: mockContext2,
mutation: mockMutationCapability
}[c];
}); });
mockDomainObject.hasCapability.andCallFake(function (c) { mockDomainObject.hasCapability.andCallFake(function (c) {
return c === 'context'; return c === 'context';
@ -299,6 +302,11 @@ define(
mockScope.$watch.calls[0].args[1](); mockScope.$watch.calls[0].args[1]();
}); });
it("listens for mutation of that object", function () {
expect(mockMutationCapability.listen)
.toHaveBeenCalledWith(jasmine.any(Function));
});
it("detects subsequent changes among linked instances", function () { it("detects subsequent changes among linked instances", function () {
var callCount = mockChangeTemplate.calls.length; var callCount = mockChangeTemplate.calls.length;

View File

@ -62,7 +62,7 @@ define([
//Don't trigger self //Don't trigger self
objectEventEmitter.off('mutation', handleMutation); objectEventEmitter.off('mutation', handleMutation);
objectEventEmitter.emit(newStyleObject.key.identifier + ":*", newStyleObject); objectEventEmitter.emit(newStyleObject.identifier.key + ":*", newStyleObject);
objectEventEmitter.on('mutation', handleMutation); objectEventEmitter.on('mutation', handleMutation);
}.bind(this); }.bind(this);