Skip to content

Commit c83da4c

Browse files
authored
fix: refactor login/logout flow and subscription handling (#1436)
1 parent 9af7a5e commit c83da4c

File tree

10 files changed

+193
-188
lines changed

10 files changed

+193
-188
lines changed

index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@
9595

9696
// for testing, normally this is set on (temporary) in the database client
9797
OneSignal._isNewVisitor = true;
98-
console.log('_isNewVisitor', OneSignal._isNewVisitor);
9998

10099
OneSignal.init({
101100
appId,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
},
8282
{
8383
"path": "./build/releases/OneSignalSDK.page.es6.js",
84-
"limit": "43.77 kB",
84+
"limit": "43.75 kB",
8585
"gzip": true
8686
},
8787
{

src/core/CoreModuleDirector.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,10 @@ export class CoreModuleDirector {
133133
logMethodCall(
134134
'CoreModuleDirector.getPushSubscriptionModelByLastKnownToken',
135135
);
136-
const lastKnownPushToken = await getPushToken();
137-
if (lastKnownPushToken) {
136+
137+
// Checking '' in case we create a temp/fake subscription on logi
138+
const lastKnownPushToken = (await getPushToken()) ?? '';
139+
if (lastKnownPushToken !== null) {
138140
return this._getSubscriptionOfTypeWithToken(
139141
SubscriptionChannel._Push,
140142
lastKnownPushToken,
@@ -151,10 +153,8 @@ export class CoreModuleDirector {
151153
SubscriptionModel | undefined
152154
> {
153155
logMethodCall('CoreModuleDirector.getPushSubscriptionModel');
154-
return (
155-
(await this._getPushSubscriptionModelByCurrentToken()) ||
156-
(await this._getPushSubscriptionModelByLastKnownToken())
157-
);
156+
const sub = await this._getPushSubscriptionModelByLastKnownToken();
157+
return (await this._getPushSubscriptionModelByCurrentToken()) || sub;
158158
}
159159

160160
public _getIdentityModel(): IdentityModel {

src/onesignal/OneSignal.test.ts

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ import {
2929
setGetUserResponse,
3030
setSendCustomEventResponse,
3131
setTransferSubscriptionResponse,
32+
setUpdateSubscriptionResponse,
3233
setUpdateUserResponse,
3334
transferSubscriptionFn,
35+
updateSubscriptionFn,
3436
updateUserFn,
3537
} from '__test__/support/helpers/requests';
3638
import {
@@ -713,7 +715,16 @@ describe('OneSignal - No Consent Required', () => {
713715
external_id: externalId,
714716
},
715717
...BASE_IDENTITY,
716-
subscriptions: [],
718+
subscriptions: [
719+
{
720+
device_model: '',
721+
device_os: DEVICE_OS,
722+
enabled: false,
723+
sdk: expect.any(String),
724+
token: '',
725+
type: 'ChromePush',
726+
},
727+
],
717728
});
718729
});
719730

@@ -747,7 +758,7 @@ describe('OneSignal - No Consent Required', () => {
747758
});
748759
});
749760

750-
test('login then accept web push permissions - it should make two user calls', async () => {
761+
test('login then accept web push permissions - it should create user then update subscription', async () => {
751762
const { promise, resolve } = Promise.withResolvers();
752763
OneSignal._emitter.on(OneSignal.EVENTS.SUBSCRIPTION_CHANGED, resolve);
753764
setGetUserResponse();
@@ -760,6 +771,7 @@ describe('OneSignal - No Consent Required', () => {
760771
},
761772
],
762773
});
774+
setUpdateSubscriptionResponse({ subscriptionId: SUB_ID });
763775

764776
OneSignal._coreDirector._subscriptionModelStore._replaceAll(
765777
[],
@@ -783,38 +795,36 @@ describe('OneSignal - No Consent Required', () => {
783795
};
784796
registerForPushNotifications();
785797

786-
// first call just sets the external id
798+
// create user call includes the empty subscription
787799
await vi.waitUntil(() => createUserFn.mock.calls.length === 1, {
788800
interval: 0,
789801
});
790-
expect(createUserFn).toHaveBeenCalledWith({
791-
identity: {
792-
external_id: externalId,
793-
},
794-
...BASE_IDENTITY,
795-
subscriptions: [],
796-
});
797-
await promise;
798-
799-
// second call creates the subscription
800-
await vi.waitUntil(() => createUserFn.mock.calls.length === 2, {
801-
interval: 1,
802-
});
802+
expect(createUserFn).toHaveBeenCalledTimes(1);
803803
expect(createUserFn).toHaveBeenCalledWith({
804804
identity: {
805805
external_id: externalId,
806806
},
807807
...BASE_IDENTITY,
808808
subscriptions: [
809809
{
810-
...BASE_SUB,
811-
token: PUSH_TOKEN,
810+
device_model: '',
811+
device_os: DEVICE_OS,
812+
enabled: false,
813+
sdk: expect.any(String),
814+
token: '',
812815
type: 'ChromePush',
813-
web_auth: 'w3cAuth',
814-
web_p256: 'w3cP256dh',
815816
},
816817
],
817818
});
819+
await promise;
820+
821+
// accepting permissions patches the existing subscription with the token
822+
await vi.waitUntil(
823+
() => updateSubscriptionFn.mock.calls.length >= 1,
824+
{
825+
interval: 1,
826+
},
827+
);
818828

819829
let pushSub: SubscriptionSchema | undefined;
820830
await vi.waitUntil(

src/onesignal/userDirector.ts

Lines changed: 0 additions & 66 deletions
This file was deleted.

src/page/bell/Message.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ export default class Message {
5959
}
6060

6161
async _display(type: string, content: string, duration = 0) {
62-
console.log('zzzzzdisplay', type, content, duration);
6362
Log._debug(`Calling display(${type}, ${content}, ${duration}).`);
6463
if (this._shown) await this._hide();
6564
this._content = decodeHtmlEntities(content);

src/page/managers/LoginManager.test.ts

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import { TestEnvironment } from '__test__/support/environment/TestEnvironment';
22
import { updateIdentityModel } from '__test__/support/helpers/setup';
33
import { SubscriptionModel } from 'src/core/models/SubscriptionModel';
4+
import { BaseSubscriptionOperation } from 'src/core/operations/BaseSubscriptionOperation';
45
import { db } from 'src/shared/database/client';
56
import Log from 'src/shared/libraries/Log';
6-
import * as userDirector from '../../onesignal/userDirector';
77
import LoginManager from './LoginManager';
88

9-
const createUserOnServerSpy = vi.spyOn(userDirector, 'createUserOnServer');
10-
119
describe('LoginManager', () => {
1210
beforeEach(() => {
1311
TestEnvironment.initialize();
@@ -52,6 +50,48 @@ describe('LoginManager', () => {
5250
expect(enqueueAndWaitSpy).toHaveBeenCalled();
5351
});
5452

53+
test('login: with existing push sub enqueues transfer operation', async () => {
54+
const mockPushSub = { id: 'push-sub-id' } as SubscriptionModel;
55+
vi.spyOn(
56+
OneSignal._coreDirector,
57+
'_getPushSubscriptionModel',
58+
).mockResolvedValue(mockPushSub);
59+
const enqueueSpy = vi.spyOn(
60+
OneSignal._coreDirector._operationRepo,
61+
'_enqueue',
62+
);
63+
vi.spyOn(
64+
OneSignal._coreDirector._operationRepo,
65+
'_enqueueAndWait',
66+
).mockResolvedValue(undefined);
67+
68+
await LoginManager.login('new-id');
69+
70+
expect(enqueueSpy).toHaveBeenCalled();
71+
const transferOp = enqueueSpy.mock.calls[0][0] as BaseSubscriptionOperation;
72+
expect(transferOp._subscriptionId).toBe('push-sub-id');
73+
});
74+
75+
test('login: without push sub creates new subscription model', async () => {
76+
vi.spyOn(
77+
OneSignal._coreDirector,
78+
'_getPushSubscriptionModel',
79+
).mockResolvedValue(undefined);
80+
vi.spyOn(
81+
OneSignal._coreDirector._operationRepo,
82+
'_enqueueAndWait',
83+
).mockResolvedValue(undefined);
84+
const addSpy = vi.spyOn(
85+
OneSignal._coreDirector._subscriptionModelStore,
86+
'_add',
87+
);
88+
89+
await LoginManager.login('new-id');
90+
91+
expect(addSpy).toHaveBeenCalled();
92+
expect(addSpy.mock.calls[0][0].token).toBe('');
93+
});
94+
5595
test('logout: no external id logs debug and returns', async () => {
5696
const debugSpy = vi
5797
.spyOn(Log, '_debug')
@@ -63,21 +103,26 @@ describe('LoginManager', () => {
63103
);
64104
});
65105

66-
test('logout: with external id and no subscriptions resets models and skips user creation', async () => {
106+
test('logout: with external id and push sub enqueues transfer and login operations', async () => {
67107
await updateIdentityModel('external_id', 'abc');
68-
await LoginManager.logout();
69-
expect(createUserOnServerSpy).not.toHaveBeenCalled();
70-
});
71-
72-
test('logout: with external id and a subscription resets models and creates anonymous user', async () => {
73-
await updateIdentityModel('external_id', 'abc');
74-
const mockSub = { id: 'sub-id' } as SubscriptionModel;
108+
const mockPushSub = { id: 'sub-id' } as SubscriptionModel;
75109
vi.spyOn(
76-
OneSignal._coreDirector._subscriptionModelStore,
77-
'_list',
78-
).mockReturnValue([mockSub]);
110+
OneSignal._coreDirector,
111+
'_getPushSubscriptionModel',
112+
).mockResolvedValue(mockPushSub);
113+
const enqueueSpy = vi.spyOn(
114+
OneSignal._coreDirector._operationRepo,
115+
'_enqueue',
116+
);
117+
vi.spyOn(
118+
OneSignal._coreDirector._operationRepo,
119+
'_enqueueAndWait',
120+
).mockResolvedValue(undefined);
79121

80122
await LoginManager.logout();
81-
expect(createUserOnServerSpy).toHaveBeenCalled();
123+
124+
expect(enqueueSpy).toHaveBeenCalled();
125+
const transferOp = enqueueSpy.mock.calls[0][0] as BaseSubscriptionOperation;
126+
expect(transferOp._subscriptionId).toBe('sub-id');
82127
});
83128
});

0 commit comments

Comments
 (0)