@@ -20,6 +20,7 @@ import {
20
20
NotificationPreference ,
21
21
NotificationAttachmentType ,
22
22
} from '../src/entity' ;
23
+ import type { UserNotificationFlags } from '../src/entity/user/User' ;
23
24
import { DataSource } from 'typeorm' ;
24
25
import createOrGetConnection from '../src/db' ;
25
26
import { usersFixture } from './fixture/user' ;
@@ -33,6 +34,8 @@ import {
33
34
NotificationPreferenceType ,
34
35
NotificationType ,
35
36
saveNotificationPreference ,
37
+ streamNotificationUsers ,
38
+ NotificationChannel ,
36
39
} from '../src/notifications/common' ;
37
40
import { postsFixture , sharedPostsFixture } from './fixture/post' ;
38
41
import { sourcesFixture } from './fixture/source' ;
@@ -1227,3 +1230,238 @@ describe('mutation subscribeNotificationPreference', () => {
1227
1230
) ;
1228
1231
} ) ;
1229
1232
} ) ;
1233
+
1234
+ describe ( 'streamNotificationUsers' , ( ) => {
1235
+ const setupNotificationAndUsers = async (
1236
+ users : {
1237
+ id : string ;
1238
+ name : string ;
1239
+ email : string ;
1240
+ notificationFlags ?: UserNotificationFlags ;
1241
+ } [ ] ,
1242
+ ) => {
1243
+ await con . getRepository ( User ) . save ( users ) ;
1244
+
1245
+ const notif = await con . getRepository ( NotificationV2 ) . save ( {
1246
+ ...notificationV2Fixture ,
1247
+ type : NotificationType . ArticleNewComment ,
1248
+ } ) ;
1249
+
1250
+ const userNotifications = users . map ( ( user ) => ( {
1251
+ userId : user . id ,
1252
+ notificationId : notif . id ,
1253
+ public : true ,
1254
+ createdAt : notificationV2Fixture . createdAt ,
1255
+ } ) ) ;
1256
+
1257
+ await con . getRepository ( UserNotification ) . insert ( userNotifications ) ;
1258
+
1259
+ return notif . id ;
1260
+ } ;
1261
+
1262
+ const streamToArray = async (
1263
+ stream : NodeJS . ReadableStream ,
1264
+ ) : Promise < { userId : string } [ ] > => {
1265
+ const results : { userId : string } [ ] = [ ] ;
1266
+ return new Promise ( ( res ) => {
1267
+ stream . on ( 'data' , ( data : { userId : string } ) => {
1268
+ results . push ( { userId : data . userId } ) ;
1269
+ } ) ;
1270
+ stream . on ( 'end' , ( ) => res ( results ) ) ;
1271
+ } ) ;
1272
+ } ;
1273
+
1274
+ it ( 'should return users for inApp channel when no preferences set' , async ( ) => {
1275
+ const users = [
1276
+ { id :
'user1' , name :
'User 1' , email :
'[email protected] ' } ,
1277
+ { id :
'user2' , name :
'User 2' , email :
'[email protected] ' } ,
1278
+ ] ;
1279
+
1280
+ const notifId = await setupNotificationAndUsers ( users ) ;
1281
+ const stream = await streamNotificationUsers (
1282
+ con ,
1283
+ notifId ,
1284
+ NotificationChannel . InApp ,
1285
+ ) ;
1286
+ const results = await streamToArray ( stream ) ;
1287
+
1288
+ expect ( results ) . toHaveLength ( 2 ) ;
1289
+ expect ( results . map ( ( r ) => r . userId ) . sort ( ) ) . toEqual ( [ 'user1' , 'user2' ] ) ;
1290
+ } ) ;
1291
+
1292
+ it ( 'should return users for email channel when no preferences set' , async ( ) => {
1293
+ const users = [
1294
+ { id :
'user3' , name :
'User 3' , email :
'[email protected] ' } ,
1295
+ { id :
'user4' , name :
'User 4' , email :
'[email protected] ' } ,
1296
+ ] ;
1297
+
1298
+ const notifId = await setupNotificationAndUsers ( users ) ;
1299
+ const stream = await streamNotificationUsers (
1300
+ con ,
1301
+ notifId ,
1302
+ NotificationChannel . Email ,
1303
+ ) ;
1304
+ const results = await streamToArray ( stream ) ;
1305
+
1306
+ expect ( results ) . toHaveLength ( 2 ) ;
1307
+ expect ( results . map ( ( r ) => r . userId ) . sort ( ) ) . toEqual ( [ 'user3' , 'user4' ] ) ;
1308
+ } ) ;
1309
+
1310
+ it ( 'should exclude users with global inApp mute preference' , async ( ) => {
1311
+ const users = [
1312
+ {
1313
+ id : 'user5' ,
1314
+ name : 'User 5' ,
1315
+
1316
+ notificationFlags : {
1317
+ [ NotificationType . ArticleNewComment ] : {
1318
+ inApp : NotificationPreferenceStatus . Muted ,
1319
+ } ,
1320
+ } ,
1321
+ } ,
1322
+ {
1323
+ id : 'user6' ,
1324
+ name : 'User 6' ,
1325
+
1326
+ notificationFlags : {
1327
+ [ NotificationType . ArticleNewComment ] : {
1328
+ inApp : NotificationPreferenceStatus . Subscribed ,
1329
+ } ,
1330
+ } ,
1331
+ } ,
1332
+ ] ;
1333
+
1334
+ const notifId = await setupNotificationAndUsers ( users ) ;
1335
+ const stream = await streamNotificationUsers (
1336
+ con ,
1337
+ notifId ,
1338
+ NotificationChannel . InApp ,
1339
+ ) ;
1340
+ const results = await streamToArray ( stream ) ;
1341
+
1342
+ expect ( results ) . toHaveLength ( 1 ) ;
1343
+ expect ( results [ 0 ] . userId ) . toBe ( 'user6' ) ;
1344
+ } ) ;
1345
+
1346
+ it ( 'should exclude users with global email mute preference' , async ( ) => {
1347
+ const users = [
1348
+ {
1349
+ id : 'user7' ,
1350
+ name : 'User 7' ,
1351
+
1352
+ notificationFlags : {
1353
+ [ NotificationType . ArticleNewComment ] : {
1354
+ email : NotificationPreferenceStatus . Muted ,
1355
+ } ,
1356
+ } ,
1357
+ } ,
1358
+ {
1359
+ id : 'user8' ,
1360
+ name : 'User 8' ,
1361
+
1362
+ notificationFlags : {
1363
+ [ NotificationType . ArticleNewComment ] : {
1364
+ email : NotificationPreferenceStatus . Subscribed ,
1365
+ } ,
1366
+ } ,
1367
+ } ,
1368
+ ] ;
1369
+
1370
+ const notifId = await setupNotificationAndUsers ( users ) ;
1371
+ const stream = await streamNotificationUsers (
1372
+ con ,
1373
+ notifId ,
1374
+ NotificationChannel . Email ,
1375
+ ) ;
1376
+ const results = await streamToArray ( stream ) ;
1377
+
1378
+ expect ( results ) . toHaveLength ( 1 ) ;
1379
+ expect ( results [ 0 ] . userId ) . toBe ( 'user8' ) ;
1380
+ } ) ;
1381
+
1382
+ it ( 'should not send notification to user with global inApp mute preference and email subscribed' , async ( ) => {
1383
+ const users = [
1384
+ {
1385
+ id : 'user9' ,
1386
+ name : 'User 9' ,
1387
+
1388
+ notificationFlags : {
1389
+ [ NotificationType . ArticleNewComment ] : {
1390
+ inApp : NotificationPreferenceStatus . Muted ,
1391
+ email : NotificationPreferenceStatus . Subscribed ,
1392
+ } ,
1393
+ } ,
1394
+ } ,
1395
+ ] ;
1396
+
1397
+ const notifId = await setupNotificationAndUsers ( users ) ;
1398
+
1399
+ const inAppStream = await streamNotificationUsers (
1400
+ con ,
1401
+ notifId ,
1402
+ NotificationChannel . InApp ,
1403
+ ) ;
1404
+ const inAppResults = await streamToArray ( inAppStream ) ;
1405
+ expect ( inAppResults ) . toHaveLength ( 0 ) ;
1406
+
1407
+ const emailStream = await streamNotificationUsers (
1408
+ con ,
1409
+ notifId ,
1410
+ NotificationChannel . Email ,
1411
+ ) ;
1412
+ const emailResults = await streamToArray ( emailStream ) ;
1413
+ expect ( emailResults ) . toHaveLength ( 1 ) ;
1414
+ expect ( emailResults [ 0 ] . userId ) . toBe ( 'user9' ) ;
1415
+ } ) ;
1416
+
1417
+ it ( 'should exclude globally muted users even if they have entity-level subscriptions' , async ( ) => {
1418
+ const users = [
1419
+ {
1420
+ id : 'user14' ,
1421
+ name : 'User 14' ,
1422
+
1423
+ notificationFlags : {
1424
+ [ NotificationType . ArticleNewComment ] : {
1425
+ inApp : NotificationPreferenceStatus . Muted ,
1426
+ } ,
1427
+ } ,
1428
+ } ,
1429
+ ] ;
1430
+
1431
+ await con . getRepository ( User ) . save ( users ) ;
1432
+ await saveFixtures ( con , Source , sourcesFixture ) ;
1433
+ await saveFixtures ( con , Post , postsFixture ) ;
1434
+
1435
+ await con . getRepository ( NotificationPreferencePost ) . save ( {
1436
+ userId : 'user14' ,
1437
+ postId : postsFixture [ 0 ] . id ,
1438
+ referenceId : postsFixture [ 0 ] . id ,
1439
+ notificationType : NotificationType . ArticleNewComment ,
1440
+ status : NotificationPreferenceStatus . Subscribed ,
1441
+ type : NotificationPreferenceType . Post ,
1442
+ } ) ;
1443
+
1444
+ const notif = await con . getRepository ( NotificationV2 ) . save ( {
1445
+ ...notificationV2Fixture ,
1446
+ type : NotificationType . ArticleNewComment ,
1447
+ } ) ;
1448
+
1449
+ await con . getRepository ( UserNotification ) . insert ( [
1450
+ {
1451
+ userId : 'user14' ,
1452
+ notificationId : notif . id ,
1453
+ public : true ,
1454
+ createdAt : notificationV2Fixture . createdAt ,
1455
+ } ,
1456
+ ] ) ;
1457
+
1458
+ const stream = await streamNotificationUsers (
1459
+ con ,
1460
+ notif . id ,
1461
+ NotificationChannel . InApp ,
1462
+ ) ;
1463
+ const results = await streamToArray ( stream ) ;
1464
+
1465
+ expect ( results ) . toHaveLength ( 0 ) ;
1466
+ } ) ;
1467
+ } ) ;
0 commit comments