// Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import { assert } from 'chai'; import * as sinon from 'sinon'; import { AreWeASubscriberService } from '../../services/areWeASubscriber'; import { explodePromise } from '../../util/explodePromise'; describe('"are we a subscriber?" service', () => { const subscriberId = new Uint8Array([1, 2, 3]); const fakeStorageDefaults = { onready: sinon.stub().callsArg(0), get: sinon.stub().withArgs('subscriberId').returns(subscriberId), }; let sandbox: sinon.SinonSandbox; let service: AreWeASubscriberService; beforeEach(() => { sandbox = sinon.createSandbox(); service = new AreWeASubscriberService(); sandbox.stub(navigator, 'onLine').get(() => true); }); it("stores false if there's no local subscriber ID", done => { const fakeServer = { getHasSubscription: sandbox.stub() }; const fakeStorage = { ...fakeStorageDefaults, get: () => undefined, put: sandbox.stub().callsFake((key, value) => { assert.strictEqual(key, 'areWeASubscriber'); assert.isFalse(value); done(); }), }; service.update(fakeStorage, fakeServer); }); it("doesn't make a network request if there's no local subscriber ID", done => { const fakeServer = { getHasSubscription: sandbox.stub() }; const fakeStorage = { ...fakeStorageDefaults, get: () => undefined, put: sandbox.stub().callsFake(() => { sinon.assert.notCalled(fakeServer.getHasSubscription); done(); }), }; service.update(fakeStorage, fakeServer); }); it('requests the subscriber ID from the server', done => { const fakeServer = { getHasSubscription: sandbox.stub().resolves(false) }; const fakeStorage = { ...fakeStorageDefaults, put: sandbox .stub() .withArgs('areWeASubscriber') .callsFake(() => { sinon.assert.calledWithExactly( fakeServer.getHasSubscription, subscriberId ); done(); }), }; service.update(fakeStorage, fakeServer); }); it("stores when we're not a subscriber", done => { const fakeServer = { getHasSubscription: sandbox.stub().resolves(false) }; const fakeStorage = { ...fakeStorageDefaults, put: sandbox.stub().callsFake((key, value) => { assert.strictEqual(key, 'areWeASubscriber'); assert.isFalse(value); done(); }), }; service.update(fakeStorage, fakeServer); }); it("stores when we're a subscriber", done => { const fakeServer = { getHasSubscription: sandbox.stub().resolves(true) }; const fakeStorage = { ...fakeStorageDefaults, put: sandbox.stub().callsFake((key, value) => { assert.strictEqual(key, 'areWeASubscriber'); assert.isTrue(value); done(); }), }; service.update(fakeStorage, fakeServer); }); it('only runs one request at a time and enqueues one other', async () => { const allDone = explodePromise(); let putCallCount = 0; const fakeServer = { getHasSubscription: sandbox.stub().resolves(false) }; const fakeStorage = { ...fakeStorageDefaults, put: sandbox.stub().callsFake(() => { putCallCount += 1; if (putCallCount === 2) { allDone.resolve(); } else if (putCallCount > 2) { throw new Error('Unexpected call to storage put'); } }), }; service.update(fakeStorage, fakeServer); service.update(fakeStorage, fakeServer); service.update(fakeStorage, fakeServer); service.update(fakeStorage, fakeServer); service.update(fakeStorage, fakeServer); await allDone.promise; sinon.assert.calledTwice(fakeServer.getHasSubscription); sinon.assert.calledTwice(fakeStorage.put); }); });