Skip to content

Commit fc7f860

Browse files
committed
pr 1
1 parent 1f1806a commit fc7f860

File tree

8 files changed

+367
-214
lines changed

8 files changed

+367
-214
lines changed

app/scripts/controllers/rewards/rewards-controller.test.ts

Lines changed: 153 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,25 @@ describe('RewardsController', () => {
11151115
describe('optIn', () => {
11161116
it('should return null when rewards are disabled', async () => {
11171117
await withController({ isDisabled: true }, async ({ controller }) => {
1118-
const result = await controller.optIn();
1118+
const result = await controller.optIn([MOCK_INTERNAL_ACCOUNT]);
1119+
1120+
expect(result).toBeNull();
1121+
});
1122+
});
1123+
1124+
it('should return null when accounts is null', async () => {
1125+
await withController({ isDisabled: false }, async ({ controller }) => {
1126+
const result = await controller.optIn(
1127+
null as unknown as InternalAccount[],
1128+
);
1129+
1130+
expect(result).toBeNull();
1131+
});
1132+
});
1133+
1134+
it('should return null when accounts is empty array', async () => {
1135+
await withController({ isDisabled: false }, async ({ controller }) => {
1136+
const result = await controller.optIn([]);
11191137

11201138
expect(result).toBeNull();
11211139
});
@@ -1126,12 +1144,6 @@ describe('RewardsController', () => {
11261144
{ isDisabled: false },
11271145
async ({ controller, mockMessengerCall }) => {
11281146
mockMessengerCall.mockImplementation((actionType) => {
1129-
if (
1130-
actionType ===
1131-
'AccountTreeController:getAccountsFromSelectedAccountGroup'
1132-
) {
1133-
return [MOCK_INTERNAL_ACCOUNT];
1134-
}
11351147
if (actionType === 'KeyringController:signPersonalMessage') {
11361148
return Promise.resolve('0xmocksignature');
11371149
}
@@ -1141,7 +1153,10 @@ describe('RewardsController', () => {
11411153
return undefined;
11421154
});
11431155

1144-
const result = await controller.optIn('REF123');
1156+
const result = await controller.optIn(
1157+
[MOCK_INTERNAL_ACCOUNT],
1158+
'REF123',
1159+
);
11451160

11461161
expect(result).toBe(MOCK_SUBSCRIPTION_ID);
11471162
expect(
@@ -1169,12 +1184,6 @@ describe('RewardsController', () => {
11691184
},
11701185
async ({ controller, mockMessengerCall }) => {
11711186
mockMessengerCall.mockImplementation((actionType) => {
1172-
if (
1173-
actionType ===
1174-
'AccountTreeController:getAccountsFromSelectedAccountGroup'
1175-
) {
1176-
return [MOCK_INTERNAL_ACCOUNT];
1177-
}
11781187
if (actionType === 'KeyringController:signPersonalMessage') {
11791188
return Promise.resolve('0xmocksignature');
11801189
}
@@ -1195,18 +1204,131 @@ describe('RewardsController', () => {
11951204
return undefined;
11961205
});
11971206

1198-
const result = await controller.optIn();
1207+
const result = await controller.optIn([MOCK_INTERNAL_ACCOUNT]);
11991208

12001209
expect(result).toBe(MOCK_SUBSCRIPTION_ID);
12011210
},
12021211
);
12031212
});
1213+
1214+
it('should throw error when all accounts fail to opt in', async () => {
1215+
await withController(
1216+
{ isDisabled: false },
1217+
async ({ controller, mockMessengerCall }) => {
1218+
mockMessengerCall.mockImplementation((actionType) => {
1219+
if (actionType === 'KeyringController:signPersonalMessage') {
1220+
return Promise.resolve('0xmocksignature');
1221+
}
1222+
if (actionType === 'RewardsDataService:mobileOptin') {
1223+
return Promise.reject(new Error('Opt-in failed'));
1224+
}
1225+
return undefined;
1226+
});
1227+
1228+
await expect(
1229+
controller.optIn([MOCK_INTERNAL_ACCOUNT]),
1230+
).rejects.toThrow(
1231+
'Failed to opt in any account from the account group',
1232+
);
1233+
},
1234+
);
1235+
});
1236+
1237+
it('should link remaining accounts when one account succeeds', async () => {
1238+
const account2: InternalAccount = {
1239+
...MOCK_INTERNAL_ACCOUNT,
1240+
id: 'account-2',
1241+
address: MOCK_ACCOUNT_ADDRESS_ALT,
1242+
};
1243+
1244+
await withController(
1245+
{
1246+
isDisabled: false,
1247+
state: {
1248+
rewardsSubscriptions: {
1249+
[MOCK_SUBSCRIPTION_ID]: MOCK_SUBSCRIPTION,
1250+
},
1251+
rewardsSubscriptionTokens: {
1252+
[MOCK_SUBSCRIPTION_ID]: MOCK_SESSION_TOKEN,
1253+
},
1254+
},
1255+
},
1256+
async ({ controller, mockMessengerCall }) => {
1257+
let optInCallCount = 0;
1258+
mockMessengerCall.mockImplementation((actionType) => {
1259+
if (actionType === 'KeyringController:signPersonalMessage') {
1260+
return Promise.resolve('0xmocksignature');
1261+
}
1262+
if (actionType === 'RewardsDataService:mobileOptin') {
1263+
optInCallCount += 1;
1264+
if (optInCallCount === 1) {
1265+
// First account fails
1266+
return Promise.reject(new Error('First account failed'));
1267+
}
1268+
// Second account succeeds
1269+
return Promise.resolve(MOCK_LOGIN_RESPONSE);
1270+
}
1271+
if (actionType === 'RewardsDataService:mobileJoin') {
1272+
return Promise.resolve(MOCK_SUBSCRIPTION);
1273+
}
1274+
return undefined;
1275+
});
1276+
1277+
const result = await controller.optIn([
1278+
MOCK_INTERNAL_ACCOUNT,
1279+
account2,
1280+
]);
1281+
1282+
expect(result).toBe(MOCK_SUBSCRIPTION_ID);
1283+
expect(optInCallCount).toBe(2);
1284+
},
1285+
);
1286+
});
1287+
1288+
it('should opt in with multiple accounts and link remaining ones', async () => {
1289+
const account2: InternalAccount = {
1290+
...MOCK_INTERNAL_ACCOUNT,
1291+
id: 'account-2',
1292+
address: MOCK_ACCOUNT_ADDRESS_ALT,
1293+
};
1294+
1295+
await withController(
1296+
{ isDisabled: false },
1297+
async ({ controller, mockMessengerCall }) => {
1298+
mockMessengerCall.mockImplementation((actionType) => {
1299+
if (actionType === 'KeyringController:signPersonalMessage') {
1300+
return Promise.resolve('0xmocksignature');
1301+
}
1302+
if (actionType === 'RewardsDataService:mobileOptin') {
1303+
return Promise.resolve(MOCK_LOGIN_RESPONSE);
1304+
}
1305+
if (actionType === 'RewardsDataService:mobileJoin') {
1306+
return Promise.resolve(MOCK_SUBSCRIPTION);
1307+
}
1308+
return undefined;
1309+
});
1310+
1311+
const result = await controller.optIn(
1312+
[MOCK_INTERNAL_ACCOUNT, account2],
1313+
'REF123',
1314+
);
1315+
1316+
expect(result).toBe(MOCK_SUBSCRIPTION_ID);
1317+
expect(
1318+
controller.state.rewardsAccounts[MOCK_CAIP_ACCOUNT],
1319+
).toMatchObject({
1320+
hasOptedIn: true,
1321+
subscriptionId: MOCK_SUBSCRIPTION_ID,
1322+
});
1323+
},
1324+
);
1325+
});
12041326
});
12051327

12061328
describe('getGeoRewardsMetadata', () => {
12071329
it('should return unknown location when rewards are disabled', async () => {
12081330
await withController({ isDisabled: true }, async ({ controller }) => {
1209-
const result = await controller.getGeoRewardsMetadata();
1331+
const result = await controller.getRewardsGeoMetadata();
12101332

12111333
expect(result).toEqual({
12121334
geoLocation: 'UNKNOWN',
@@ -1226,15 +1348,15 @@ describe('RewardsController', () => {
12261348
return undefined;
12271349
});
12281350

1229-
const result = await controller.getGeoRewardsMetadata();
1351+
const result = await controller.getRewardsGeoMetadata();
12301352

12311353
expect(result).toEqual({
12321354
geoLocation: 'US',
12331355
optinAllowedForGeo: true,
12341356
});
12351357

12361358
// Verify caching - second call should not fetch again
1237-
const cachedResult = await controller.getGeoRewardsMetadata();
1359+
const cachedResult = await controller.getRewardsGeoMetadata();
12381360
expect(cachedResult).toEqual(result);
12391361
},
12401362
);
@@ -1251,7 +1373,7 @@ describe('RewardsController', () => {
12511373
return undefined;
12521374
});
12531375

1254-
const result = await controller.getGeoRewardsMetadata();
1376+
const result = await controller.getRewardsGeoMetadata();
12551377

12561378
expect(result).toEqual({
12571379
geoLocation: 'UK',
@@ -2562,44 +2684,27 @@ describe('Additional RewardsController edge cases', () => {
25622684

25632685
describe('optIn - edge cases', () => {
25642686
it('should return null when no accounts in account group', async () => {
2565-
await withController(
2566-
{ isDisabled: false },
2567-
async ({ controller, mockMessengerCall }) => {
2568-
mockMessengerCall.mockImplementation((actionType) => {
2569-
if (
2570-
actionType ===
2571-
'AccountTreeController:getAccountsFromSelectedAccountGroup'
2572-
) {
2573-
return null;
2574-
}
2575-
return undefined;
2576-
});
2577-
2578-
const result = await controller.optIn();
2687+
await withController({ isDisabled: false }, async ({ controller }) => {
2688+
const result = await controller.optIn([]);
25792689

2580-
expect(result).toBeNull();
2581-
},
2582-
);
2690+
expect(result).toBeNull();
2691+
});
25832692
});
25842693

25852694
it('should throw error when all accounts fail to opt in', async () => {
25862695
await withController(
25872696
{ isDisabled: false },
25882697
async ({ controller, mockMessengerCall }) => {
25892698
mockMessengerCall.mockImplementation((actionType) => {
2590-
if (
2591-
actionType ===
2592-
'AccountTreeController:getAccountsFromSelectedAccountGroup'
2593-
) {
2594-
return [MOCK_INTERNAL_ACCOUNT];
2595-
}
25962699
if (actionType === 'KeyringController:signPersonalMessage') {
25972700
return Promise.reject(new Error('Signature failed'));
25982701
}
25992702
return undefined;
26002703
});
26012704

2602-
await expect(controller.optIn()).rejects.toThrow(
2705+
await expect(
2706+
controller.optIn([MOCK_INTERNAL_ACCOUNT]),
2707+
).rejects.toThrow(
26032708
'Failed to opt in any account from the account group',
26042709
);
26052710
},
@@ -2617,12 +2722,6 @@ describe('Additional RewardsController edge cases', () => {
26172722
{ isDisabled: false },
26182723
async ({ controller, mockMessengerCall }) => {
26192724
mockMessengerCall.mockImplementation((actionType) => {
2620-
if (
2621-
actionType ===
2622-
'AccountTreeController:getAccountsFromSelectedAccountGroup'
2623-
) {
2624-
return [MOCK_INTERNAL_ACCOUNT, account2];
2625-
}
26262725
if (actionType === 'KeyringController:signPersonalMessage') {
26272726
return Promise.resolve('0xmocksignature');
26282727
}
@@ -2635,7 +2734,10 @@ describe('Additional RewardsController edge cases', () => {
26352734
return undefined;
26362735
});
26372736

2638-
const result = await controller.optIn('REF123');
2737+
const result = await controller.optIn(
2738+
[MOCK_INTERNAL_ACCOUNT, account2],
2739+
'REF123',
2740+
);
26392741

26402742
expect(result).toBe(MOCK_SUBSCRIPTION_ID);
26412743
},
@@ -3050,7 +3152,7 @@ describe('Additional RewardsController edge cases', () => {
30503152
return undefined;
30513153
});
30523154

3053-
const result = await controller.getGeoRewardsMetadata();
3155+
const result = await controller.getRewardsGeoMetadata();
30543156

30553157
expect(result).toEqual({
30563158
geoLocation: 'UNKNOWN',

0 commit comments

Comments
 (0)