diff --git a/js/blocked_number_controller.js b/js/blocked_number_controller.js
index e390961d2..4cbb348de 100644
--- a/js/blocked_number_controller.js
+++ b/js/blocked_number_controller.js
@@ -22,6 +22,7 @@
return blockedNumbers;
},
reset() {
+ this.unblockAll();
blockedNumbers.reset([]);
},
load() {
@@ -61,18 +62,15 @@
unblock(number) {
storage.removeBlockedNumber(number);
- // Make sure we don't add duplicates
+ // Remove the model from our collection
const model = blockedNumbers.getNumber(number);
if (model) {
blockedNumbers.remove(model);
}
},
unblockAll() {
- const all = blockedNumbers.models;
- all.forEach(number => {
- storage.removeBlockedNumber(number);
- blockedNumbers.remove(number);
- });
+ const numbers = blockedNumbers.map(m => m.get('number'));
+ numbers.forEach(n => this.unblock(n));
},
isBlocked(number) {
return storage.isBlocked(number);
diff --git a/test/blocked_number_controller_test.js b/test/blocked_number_controller_test.js
new file mode 100644
index 000000000..de9fbd2d4
--- /dev/null
+++ b/test/blocked_number_controller_test.js
@@ -0,0 +1,153 @@
+/* global textsecure, BlockedNumberController, storage */
+
+'use strict';
+
+describe('Blocked Number Controller', () => {
+
+ beforeEach(async () => {
+ const numbers = storage.getBlockedNumbers();
+ numbers.forEach(storage.removeBlockedNumber);
+ window.getBlockedNumbers().reset([]);
+ });
+
+ describe('getAll', () => {
+ it('returns our blocked numbers', () => {
+ assert.isEmpty(BlockedNumberController.getAll().models);
+
+ BlockedNumberController.block('1');
+ BlockedNumberController.block('2');
+ assert.lengthOf(BlockedNumberController.getAll().models, 2);
+ });
+ });
+
+ describe('reset', () => {
+ it('clears blocked numbers', () => {
+ BlockedNumberController.block('1');
+ assert.isNotEmpty(BlockedNumberController.getAll().models);
+
+ BlockedNumberController.reset();
+ assert.isEmpty(BlockedNumberController.getAll().models);
+ });
+ });
+
+ describe('load', () => {
+ it('loads blocked numbers from storage', () => {
+ BlockedNumberController.load();
+ assert.isEmpty(window.getBlockedNumbers().models);
+
+ storage.addBlockedNumber('1');
+ storage.addBlockedNumber('2');
+ BlockedNumberController.load();
+ assert.lengthOf(window.getBlockedNumbers().models, 2);
+ });
+
+ it('throws if we have already loaded numbers', () => {
+ storage.addBlockedNumber('2');
+ BlockedNumberController.load();
+ assert.throws(() => BlockedNumberController.load(), 'BlockedNumberController: Already loaded!');
+ });
+
+ it('throws if storage is invalid', () => {
+ const _storage = window.storage;
+ window.storage = null;
+ assert.throws(() => BlockedNumberController.load(), 'BlockedNumberController: Could not load blocked numbers');
+ window.storage = _storage;
+ });
+ });
+
+ describe('block', () => {
+ beforeEach(() => {
+ BlockedNumberController.load();
+ assert.isEmpty(BlockedNumberController.getAll().models);
+ });
+
+ it('adds number to the blocked list', () => {
+ assert.isEmpty(storage.getBlockedNumbers());
+
+ BlockedNumberController.block('1');
+
+ const numbers = BlockedNumberController.getAll().models;
+ assert.lengthOf(numbers, 1);
+ assert.strictEqual('1', numbers[0].get('number'))
+ assert.deepEqual(['1'], storage.getBlockedNumbers());
+ });
+
+ it('only blocks the same number once', () => {
+ BlockedNumberController.block('2');
+ BlockedNumberController.block('2');
+ assert.lengthOf(BlockedNumberController.getAll().models, 1);
+ assert.deepEqual(['2'], storage.getBlockedNumbers());
+ });
+
+ it('does not block our own number', () => {
+ BlockedNumberController.block(textsecure.storage.user.getNumber());
+ assert.isEmpty(BlockedNumberController.getAll().models);
+ assert.isEmpty(storage.getBlockedNumbers());
+ });
+ });
+
+ describe('unblock', () => {
+ beforeEach(() => {
+ BlockedNumberController.load();
+ assert.isEmpty(BlockedNumberController.getAll().models);
+ });
+
+ it('removes number from the blocked list', () => {
+ BlockedNumberController.block('1');
+ BlockedNumberController.block('2');
+
+ assert.lengthOf(BlockedNumberController.getAll().models, 2);
+ assert.lengthOf(storage.getBlockedNumbers(), 2);
+
+ BlockedNumberController.unblock('1');
+
+ const numbers = BlockedNumberController.getAll().models;
+ assert.lengthOf(numbers, 1);
+ assert.isEmpty(numbers.filter(n => n.get('number') === '1'));
+ assert.deepEqual(['2'], storage.getBlockedNumbers());
+ });
+
+ it('removes number from the blocked list even if it is not present in the collection', () => {
+ BlockedNumberController.block('1');
+ BlockedNumberController.block('2');
+ window.getBlockedNumbers().reset([]);
+
+ assert.isEmpty(window.getBlockedNumbers().models);
+ assert.lengthOf(storage.getBlockedNumbers(), 2);
+
+ BlockedNumberController.unblock('1');
+ assert.deepEqual(['2'], storage.getBlockedNumbers());
+ });
+ });
+
+ describe('unblockAll', () => {
+ it('removes all our blocked numbers', () => {
+ BlockedNumberController.load();
+
+ BlockedNumberController.block('1');
+ BlockedNumberController.block('2');
+ BlockedNumberController.block('3');
+
+ assert.lengthOf(BlockedNumberController.getAll().models, 3);
+ assert.lengthOf(storage.getBlockedNumbers(), 3);
+
+ BlockedNumberController.unblockAll();
+
+ assert.lengthOf(BlockedNumberController.getAll().models, 0);
+ assert.lengthOf(storage.getBlockedNumbers(), 0);
+ });
+ });
+
+ describe('isBlocked', () => {
+ it('returns whether a number is blocked', () => {
+ BlockedNumberController.load();
+
+ BlockedNumberController.block('1');
+ assert.isOk(BlockedNumberController.isBlocked('1'));
+ assert.isNotOk(BlockedNumberController.isBlocked('2'));
+
+ BlockedNumberController.unblock('1');
+ assert.isNotOk(BlockedNumberController.isBlocked('1'));
+ });
+ });
+});
\ No newline at end of file
diff --git a/test/index.html b/test/index.html
index 55a02a55d..80e223b1c 100644
--- a/test/index.html
+++ b/test/index.html
@@ -429,6 +429,7 @@
+