Commit f308df84 authored by Robert Knight's avatar Robert Knight

Use real annotationUI object rather than fake in tests

Since putting the annotationUI store into the desired state and
asserting that the state is correct after interactions is quite
straightforward, using the real object rather than a fake seems
appropriate at present.
parent 76e14557
......@@ -2,7 +2,7 @@
var angular = require('angular');
var createFakeStore = require('./create-fake-store');
var annotationUIFactory = require('../annotation-ui');
describe('AnnotationUIController', function () {
var $scope;
......@@ -24,16 +24,7 @@ describe('AnnotationUIController', function () {
$scope = $rootScope.$new();
$scope.search = {};
var store = createFakeStore({
selectedAnnotationMap: null,
focusedAnnotationsMap: null,
});
annotationUI = {
removeSelectedAnnotation: sandbox.stub(),
setState: store.setState,
getState: store.getState,
subscribe: store.subscribe,
};
annotationUI = annotationUIFactory({});
$controller('AnnotationUIController', {
$scope: $scope,
......@@ -46,30 +37,34 @@ describe('AnnotationUIController', function () {
});
it('updates the view when the selection changes', function () {
annotationUI.setState({selectedAnnotationMap: { 1: true, 2: true }});
annotationUI.selectAnnotations(['1','2']);
assert.deepEqual($scope.selectedAnnotations, { 1: true, 2: true });
});
it('updates the selection counter when the selection changes', function () {
annotationUI.setState({selectedAnnotationMap: { 1: true, 2: true }});
annotationUI.selectAnnotations(['1','2']);
assert.deepEqual($scope.selectedAnnotationsCount, 2);
});
it('clears the selection when no annotations are selected', function () {
annotationUI.setState({selectedAnnotationMap: null});
annotationUI.selectAnnotations([]);
assert.deepEqual($scope.selectedAnnotations, null);
assert.deepEqual($scope.selectedAnnotationsCount, 0);
});
it('updates the focused annotations when the focus map changes', function () {
annotationUI.setState({focusedAnnotationMap: { 1: true, 2: true }});
annotationUI.focusAnnotations([
{$$tag: '1'},
{$$tag: '2'},
]);
assert.deepEqual($scope.focusedAnnotations, { 1: true, 2: true });
});
describe('on annotationDeleted', function () {
it('removes the deleted annotation from the selection', function () {
annotationUI.selectAnnotations(['1']);
$rootScope.$emit('annotationDeleted', { id: 1 });
assert.calledWith(annotationUI.removeSelectedAnnotation, { id: 1 });
assert.equal(annotationUI.getState().selectedAnnotationMap, null);
});
});
});
......@@ -2,14 +2,14 @@
var angular = require('angular');
var createFakeStore = require('./create-fake-store');
var annotationUIFactory = require('../annotation-ui');
describe('AnnotationUISync', function () {
var sandbox = sinon.sandbox.create();
var $digest;
var publish;
var fakeBridge;
var fakeAnnotationUI;
var annotationUI;
var fakeAnnotationSync;
var createAnnotationUISync;
var createChannel = function () {
......@@ -45,23 +45,18 @@ describe('AnnotationUISync', function () {
fakeAnnotationSync = {
getAnnotationForTag: function (tag) {
return { id: Number(tag.replace('tag', '')) };
}
return {
id: Number(tag.replace('tag', '')),
$$tag: tag,
};
var store = createFakeStore({visibleHighlights: false});
fakeAnnotationUI = {
focusAnnotations: sandbox.stub(),
selectAnnotations: sandbox.stub(),
xorSelectedAnnotations: sandbox.stub(),
setShowHighlights: sandbox.stub(),
getState: store.getState,
}
};
annotationUI = annotationUIFactory({});
createAnnotationUISync = function () {
new AnnotationUISync(
$rootScope, fakeWindow, fakeBridge, fakeAnnotationSync,
fakeAnnotationUI
annotationUI
);
};
}));
......@@ -97,10 +92,11 @@ describe('AnnotationUISync', function () {
it('updates the annotationUI to include the shown annotations', function () {
createAnnotationUISync();
publish('showAnnotations', ['tag1', 'tag2', 'tag3']);
assert.called(fakeAnnotationUI.selectAnnotations);
assert.calledWith(fakeAnnotationUI.selectAnnotations, [
{ id: 1 }, { id: 2 }, { id: 3 }
]);
assert.deepEqual(annotationUI.getState().selectedAnnotationMap, {
1: true,
2: true,
3: true,
});
});
it('triggers a digest', function () {
......@@ -114,10 +110,11 @@ describe('AnnotationUISync', function () {
it('updates the annotationUI to show the provided annotations', function () {
createAnnotationUISync();
publish('focusAnnotations', ['tag1', 'tag2', 'tag3']);
assert.called(fakeAnnotationUI.focusAnnotations);
assert.calledWith(fakeAnnotationUI.focusAnnotations, [
{ id: 1 }, { id: 2 }, { id: 3 }
]);
assert.deepEqual(annotationUI.getState().focusedAnnotationMap, {
tag1: true,
tag2: true,
tag3: true,
});
});
it('triggers a digest', function () {
......@@ -131,10 +128,11 @@ describe('AnnotationUISync', function () {
it('updates the annotationUI to show the provided annotations', function () {
createAnnotationUISync();
publish('toggleAnnotationSelection', ['tag1', 'tag2', 'tag3']);
assert.called(fakeAnnotationUI.xorSelectedAnnotations);
assert.calledWith(fakeAnnotationUI.xorSelectedAnnotations, [
{ id: 1 }, { id: 2 }, { id: 3 }
]);
assert.deepEqual(annotationUI.getState().selectedAnnotationMap, {
1: true,
2: true,
3: true,
});
});
it('triggers a digest', function () {
......@@ -148,7 +146,7 @@ describe('AnnotationUISync', function () {
it('updates the annotationUI state', function () {
createAnnotationUISync();
publish('setVisibleHighlights', true);
assert.calledWith(fakeAnnotationUI.setShowHighlights, true);
assert.equal(annotationUI.getState().visibleHighlights, true);
});
it('notifies the other frames of the change', function () {
......
'use strict';
var redux = require('redux');
function reducer(state, action) {
if (action.type === 'STATE_UPDATE') {
return Object.assign({}, state, action.update);
} else {
return state;
}
}
/**
* Creates a fake Redux store for use in tests.
*
* Unlike a normal Redux store where the user provides a function that
* transforms the state in response to actions and calls dispatch() to update
* the state when actions occur, this store has a setState() method for
* replacing state fields directly.
*/
function createFakeStore(initialState) {
var store = redux.createStore(reducer, initialState);
store.setState = function (update) {
store.dispatch({
type: 'STATE_UPDATE',
update: update,
});
};
return store;
}
module.exports = createFakeStore;
......@@ -5,7 +5,7 @@ var inherits = require('inherits');
var proxyquire = require('proxyquire');
var EventEmitter = require('tiny-emitter');
var createFakeStore = require('./create-fake-store');
var annotationUIFactory = require('../annotation-ui');
var events = require('../events');
var noCallThru = require('./util').noCallThru;
......@@ -29,8 +29,8 @@ inherits(FakeSearchClient, EventEmitter);
describe('WidgetController', function () {
var $scope = null;
var $rootScope = null;
var annotationUI = null;
var fakeAnnotationMapper = null;
var fakeAnnotationUI = null;
var fakeCrossFrame = null;
var fakeDrafts = null;
var fakeStore = null;
......@@ -63,28 +63,7 @@ describe('WidgetController', function () {
unloadAnnotations: sandbox.spy()
};
var store = createFakeStore({selectedAnnotationMap: {}});
fakeAnnotationUI = {
clearSelectedAnnotations: sandbox.spy(),
hasSelectedAnnotations: function () {
return !!this.getState().selectedAnnotationMap &&
Object.keys(this.getState().selectedAnnotationMap).length > 0;
},
getState: store.getState,
subscribe: store.subscribe,
_select: function (ids) {
if (!ids.length) {
store.setState({selectedAnnotationMap: null});
return;
}
store.setState({
selectedAnnotationMap: ids.reduce(function (map, id) {
map[id] = true;
return map;
}, {}),
});
},
};
annotationUI = annotationUIFactory({});
fakeCrossFrame = {
call: sinon.stub(),
frames: [],
......@@ -125,7 +104,7 @@ describe('WidgetController', function () {
};
$provide.value('annotationMapper', fakeAnnotationMapper);
$provide.value('annotationUI', fakeAnnotationUI);
$provide.value('annotationUI', annotationUI);
$provide.value('crossframe', fakeCrossFrame);
$provide.value('drafts', fakeDrafts);
$provide.value('store', fakeStore);
......@@ -187,7 +166,7 @@ describe('WidgetController', function () {
beforeEach(function () {
fakeCrossFrame.frames = [{uri: uri}];
fakeAnnotationUI._select([id]);
annotationUI.selectAnnotations([id]);
$scope.$digest();
});
......@@ -232,7 +211,7 @@ describe('WidgetController', function () {
beforeEach(function () {
fakeCrossFrame.frames = [{uri: uri}];
fakeAnnotationUI._select([id]);
annotationUI.selectAnnotations([id]);
fakeGroups.focused = function () { return { id: 'private-group' }; };
$scope.$digest();
});
......@@ -248,7 +227,7 @@ describe('WidgetController', function () {
describe('when an annotation is anchored', function () {
it('focuses and scrolls to the annotation if already selected', function () {
var uri = 'http://example.com';
fakeAnnotationUI._select(['123']);
annotationUI.selectAnnotations(['123']);
fakeCrossFrame.frames.push({uri: uri});
var annot = {
$$tag: 'atag',
......@@ -311,21 +290,21 @@ describe('WidgetController', function () {
describe('direct linking messages', function () {
it('displays a message if the selection is unavailable', function () {
fakeAnnotationUI._select(['missing']);
annotationUI.selectAnnotations(['missing']);
fakeThreading.idTable = {'123': {}};
$scope.$digest();
assert.isTrue($scope.selectedAnnotationUnavailable());
});
it('does not show a message if the selection is available', function () {
fakeAnnotationUI._select(['123']);
annotationUI.selectAnnotations(['123']);
fakeThreading.idTable = {'123': {}};
$scope.$digest();
assert.isFalse($scope.selectedAnnotationUnavailable());
});
it('does not a show a message if there is no selection', function () {
fakeAnnotationUI._select([]);
annotationUI.selectAnnotations([]);
$scope.$digest();
assert.isFalse($scope.selectedAnnotationUnavailable());
});
......@@ -334,7 +313,7 @@ describe('WidgetController', function () {
$scope.auth = {
status: 'signed-out'
};
fakeAnnotationUI._select(['123']);
annotationUI.selectAnnotations(['123']);
fakeThreading.idTable = {'123': {}};
$scope.$digest();
assert.isTrue($scope.shouldShowLoggedOutMessage());
......@@ -344,7 +323,7 @@ describe('WidgetController', function () {
$scope.auth = {
status: 'signed-out'
};
fakeAnnotationUI._select(['missing']);
annotationUI.selectAnnotations(['missing']);
fakeThreading.idTable = {'123': {}};
$scope.$digest();
assert.isFalse($scope.shouldShowLoggedOutMessage());
......@@ -354,7 +333,7 @@ describe('WidgetController', function () {
$scope.auth = {
status: 'signed-out'
};
fakeAnnotationUI._select([]);
annotationUI.selectAnnotations([]);
$scope.$digest();
assert.isFalse($scope.shouldShowLoggedOutMessage());
});
......@@ -363,7 +342,7 @@ describe('WidgetController', function () {
$scope.auth = {
status: 'signed-in'
};
fakeAnnotationUI._select(['123']);
annotationUI.selectAnnotations(['123']);
fakeThreading.idTable = {'123': {}};
$scope.$digest();
assert.isFalse($scope.shouldShowLoggedOutMessage());
......@@ -374,7 +353,7 @@ describe('WidgetController', function () {
status: 'signed-out'
};
delete fakeSettings.annotations;
fakeAnnotationUI._select(['123']);
annotationUI.selectAnnotations(['123']);
fakeThreading.idTable = {'123': {}};
$scope.$digest();
assert.isFalse($scope.shouldShowLoggedOutMessage());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment