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 @@ +