ASRouterStorage.test.js (24614B)
1 import { ASRouterStorage } from "modules/ASRouterStorage.sys.mjs"; 2 import { GlobalOverrider } from "tests/unit/utils"; 3 4 let overrider = new GlobalOverrider(); 5 6 describe("ASRouterStorage", () => { 7 let sandbox; 8 let indexedDB; 9 let storage; 10 beforeEach(() => { 11 sandbox = sinon.createSandbox(); 12 indexedDB = { 13 open: sandbox.stub().resolves({}), 14 deleteDatabase: sandbox.stub().resolves(), 15 }; 16 overrider.set({ IndexedDB: indexedDB }); 17 storage = new ASRouterStorage({ 18 storeNames: ["storage_test"], 19 telemetry: { handleUndesiredEvent: sandbox.stub() }, 20 }); 21 }); 22 afterEach(() => { 23 sandbox.restore(); 24 }); 25 it("should throw if required arguments not provided", () => { 26 assert.throws(() => new ASRouterStorage({ telemetry: true })); 27 }); 28 describe(".db", () => { 29 it("should not throw an error when accessing db", async () => { 30 assert.ok(storage.db); 31 }); 32 33 it("should delete and recreate the db if opening db fails", async () => { 34 const newDb = {}; 35 indexedDB.open.onFirstCall().rejects(new Error("fake error")); 36 indexedDB.open.onSecondCall().resolves(newDb); 37 38 const db = await storage.db; 39 assert.calledOnce(indexedDB.deleteDatabase); 40 assert.calledTwice(indexedDB.open); 41 assert.equal(db, newDb); 42 }); 43 }); 44 describe("#getDbTable", () => { 45 let testStorage; 46 let storeStub; 47 beforeEach(() => { 48 storeStub = { 49 getAll: sandbox.stub().resolves(), 50 getAllKeys: sandbox.stub().resolves(), 51 get: sandbox.stub().resolves(), 52 put: sandbox.stub().resolves(), 53 }; 54 sandbox.stub(storage, "_getStore").resolves(storeStub); 55 testStorage = storage.getDbTable("storage_test"); 56 }); 57 it("should reverse key value parameters for put", async () => { 58 await testStorage.set("key", "value"); 59 60 assert.calledOnce(storeStub.put); 61 assert.calledWith(storeStub.put, "value", "key"); 62 }); 63 it("should return the correct value for get", async () => { 64 storeStub.get.withArgs("foo").resolves("foo"); 65 66 const result = await testStorage.get("foo"); 67 68 assert.calledOnce(storeStub.get); 69 assert.equal(result, "foo"); 70 }); 71 it("should return the correct value for getAll", async () => { 72 storeStub.getAll.resolves(["bar"]); 73 74 const result = await testStorage.getAll(); 75 76 assert.calledOnce(storeStub.getAll); 77 assert.deepEqual(result, ["bar"]); 78 }); 79 it("should return the correct value for getAllKeys", async () => { 80 storeStub.getAllKeys.resolves(["key1", "key2", "key3"]); 81 82 const result = await testStorage.getAllKeys(); 83 84 assert.calledOnce(storeStub.getAllKeys); 85 assert.deepEqual(result, ["key1", "key2", "key3"]); 86 }); 87 it("should query the correct object store", async () => { 88 await testStorage.get(); 89 90 assert.calledOnce(storage._getStore); 91 assert.calledWithExactly(storage._getStore, "storage_test"); 92 }); 93 it("should throw if table is not found", () => { 94 assert.throws(() => storage.getDbTable("undefined_store")); 95 }); 96 }); 97 it("should get the correct objectStore when calling _getStore", async () => { 98 const objectStoreStub = sandbox.stub(); 99 indexedDB.open.resolves({ objectStore: objectStoreStub }); 100 101 await storage._getStore("foo"); 102 103 assert.calledOnce(objectStoreStub); 104 assert.calledWithExactly(objectStoreStub, "foo", "readwrite"); 105 }); 106 it("should create a db with the correct store name", async () => { 107 const dbStub = { 108 createObjectStore: sandbox.stub(), 109 objectStoreNames: { contains: sandbox.stub().returns(false) }, 110 }; 111 await storage.db; 112 113 // call the cb with a stub 114 indexedDB.open.args[0][2](dbStub); 115 116 assert.calledOnce(dbStub.createObjectStore); 117 assert.calledWithExactly(dbStub.createObjectStore, "storage_test"); 118 }); 119 it("should handle an array of object store names", async () => { 120 storage = new ASRouterStorage({ 121 storeNames: ["store1", "store2"], 122 telemetry: {}, 123 }); 124 const dbStub = { 125 createObjectStore: sandbox.stub(), 126 objectStoreNames: { contains: sandbox.stub().returns(false) }, 127 }; 128 await storage.db; 129 130 // call the cb with a stub 131 indexedDB.open.args[0][2](dbStub); 132 133 assert.calledTwice(dbStub.createObjectStore); 134 assert.calledWith(dbStub.createObjectStore, "store1"); 135 assert.calledWith(dbStub.createObjectStore, "store2"); 136 }); 137 it("should skip creating existing stores", async () => { 138 storage = new ASRouterStorage({ 139 storeNames: ["store1", "store2"], 140 telemetry: {}, 141 }); 142 const dbStub = { 143 createObjectStore: sandbox.stub(), 144 objectStoreNames: { contains: sandbox.stub().returns(true) }, 145 }; 146 await storage.db; 147 148 // call the cb with a stub 149 indexedDB.open.args[0][2](dbStub); 150 151 assert.notCalled(dbStub.createObjectStore); 152 }); 153 describe("#_requestWrapper", () => { 154 it("should return a successful result", async () => { 155 const result = await storage._requestWrapper(() => 156 Promise.resolve("foo") 157 ); 158 159 assert.equal(result, "foo"); 160 assert.notCalled(storage.telemetry.handleUndesiredEvent); 161 }); 162 it("should report failures", async () => { 163 try { 164 await storage._requestWrapper(() => Promise.reject(new Error())); 165 } catch (e) { 166 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 167 } 168 }); 169 }); 170 }); 171 172 function assertMessageBlockedTransaction(mockConnection, expectedMessageId) { 173 assert.callCount(mockConnection.executeCached, 2); 174 175 const [call1, call2] = [ 176 mockConnection.executeCached.getCall(0), 177 mockConnection.executeCached.getCall(1), 178 ]; 179 180 assert.match(call1.args[0], /INSERT INTO MessagingSystemMessageBlocklist/); 181 assert.match(call2.args[0], /DELETE FROM MessagingSystemMessageImpressions/); 182 183 assert.deepEqual(call1.args[1], { messageId: expectedMessageId }); 184 assert.deepEqual(call2.args[1], { messageId: expectedMessageId }); 185 } 186 187 describe("Shared database methods", () => { 188 let sandbox; 189 let mockConnection; 190 let storage; 191 let errorStub; 192 193 beforeEach(() => { 194 sandbox = sinon.createSandbox(); 195 errorStub = sandbox.stub(); 196 197 storage = new ASRouterStorage({ 198 storeNames: ["storage_test"], 199 telemetry: { handleUndesiredEvent: sandbox.stub() }, 200 }); 201 202 mockConnection = { 203 executeCached: sandbox.stub(), 204 executeBeforeShutdown: sandbox.stub(), 205 executeTransaction: sandbox.stub(), 206 }; 207 208 mockConnection.executeBeforeShutdown.callsFake(async (label, fn) => { 209 return await fn(); 210 }); 211 mockConnection.executeTransaction.callsFake(async fn => { 212 return await fn(); 213 }); 214 215 overrider.set({ 216 ASRouterPreferences: { 217 console: { 218 error: errorStub, 219 }, 220 }, 221 IndexedDB: indexedDB, 222 ProfilesDatastoreService: { 223 getConnection: sandbox.stub().resolves(mockConnection), 224 notify: sandbox.stub(), 225 }, 226 }); 227 }); 228 229 afterEach(() => { 230 sandbox.restore(); 231 overrider.restore(); 232 }); 233 234 describe("#getSharedMessageImpressions", () => { 235 it("should return message impressions data when records exist", async () => { 236 const mockRows = [ 237 { 238 getResultByName: columnName => { 239 if (columnName === "messageId") { 240 return "message1"; 241 } 242 if (columnName === "impressions") { 243 return JSON.stringify([123, 456]); 244 } 245 return null; 246 }, 247 }, 248 { 249 getResultByName: columnName => { 250 if (columnName === "messageId") { 251 return "message2"; 252 } 253 if (columnName === "impressions") { 254 return JSON.stringify([123, 456, 789]); 255 } 256 return null; 257 }, 258 }, 259 ]; 260 261 mockConnection.executeCached.resolves(mockRows); 262 263 const result = await storage.getSharedMessageImpressions(); 264 265 // Execute should be called with expected SQL 266 assert.calledOnce(mockConnection.executeCached); 267 assert.calledWith( 268 mockConnection.executeCached, 269 "SELECT messageId, json(impressions) AS impressions FROM MessagingSystemMessageImpressions;" 270 ); 271 272 assert.deepEqual(result, { 273 message1: [123, 456], 274 message2: [123, 456, 789], 275 }); 276 }); 277 278 it("should return null when no records exist", async () => { 279 mockConnection.executeCached.resolves([]); 280 281 const result = await storage.getSharedMessageImpressions(); 282 283 assert.ok(result === null); 284 }); 285 286 it("should handle database errors and call telemetry", async () => { 287 const error = new Error("Database connection failed"); 288 mockConnection.executeCached.rejects(error); 289 290 const result = await storage.getSharedMessageImpressions(); 291 292 assert.equal(result, null); 293 assert.calledOnce(errorStub); 294 assert.calledWith( 295 errorStub, 296 "ASRouterStorage: Failed reading from MessagingSystemMessageImpressions", 297 error 298 ); 299 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 300 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 301 event: "SHARED_DB_READ_FAILED", 302 }); 303 }); 304 305 it("should return null when getConnection throws an error", async () => { 306 const connectionError = new Error("Failed to get database connection"); 307 308 overrider.set({ 309 ASRouterPreferences: { 310 console: { error: errorStub }, 311 }, 312 ProfilesDatastoreService: { 313 getConnection: sandbox.stub().rejects(connectionError), 314 notify: sandbox.stub(), 315 }, 316 }); 317 318 const result = await storage.getSharedMessageImpressions(); 319 320 assert.equal(result, null); 321 assert.calledOnce(errorStub); 322 assert.calledWith( 323 errorStub, 324 "ASRouterStorage: Failed reading from MessagingSystemMessageImpressions", 325 connectionError 326 ); 327 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 328 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 329 event: "SHARED_DB_READ_FAILED", 330 }); 331 }); 332 333 it("should return null when getConnection returns null", async () => { 334 overrider.set({ 335 ProfilesDatastoreService: { 336 getConnection: sandbox.stub().resolves(null), 337 notify: sandbox.stub(), 338 }, 339 }); 340 341 const result = await storage.getSharedMessageImpressions(); 342 343 assert.equal(result, null); 344 }); 345 }); 346 347 describe("#setSharedMessageImpressions", () => { 348 it("should return a true success state when the transaction succeeds", async () => { 349 mockConnection.executeCached.resolves(); 350 351 const result = await storage.setSharedMessageImpressions( 352 "test_message", 353 [123, 456] 354 ); 355 356 assert.equal(result, true); 357 assert.calledOnce(mockConnection.executeBeforeShutdown); 358 assert.calledWith( 359 mockConnection.executeBeforeShutdown, 360 "ASRouter: setSharedMessageImpressions" 361 ); 362 }); 363 364 it("should return a false success state when the transaction fails", async () => { 365 const error = new Error("Database write failed"); 366 mockConnection.executeCached.rejects(error); 367 368 const result = await storage.setSharedMessageImpressions( 369 "test_message", 370 [123, 456] 371 ); 372 373 assert.equal(result, false); 374 assert.calledOnce(errorStub); 375 assert.calledWith( 376 errorStub, 377 "ASRouterStorage: Failed writing to MessagingSystemMessageImpressions", 378 error 379 ); 380 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 381 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 382 event: "SHARED_DB_WRITE_FAILED", 383 }); 384 }); 385 386 it("should gracefully fail when called with no message ID", async () => { 387 const result = await storage.setSharedMessageImpressions( 388 null, 389 [123, 456] 390 ); 391 392 assert.equal(result, false); 393 assert.calledOnce(errorStub); 394 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 395 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 396 event: "SHARED_DB_WRITE_FAILED", 397 }); 398 }); 399 400 it("should execute the appropriate sql query with the appropriate message ID", async () => { 401 mockConnection.executeCached.resolves(); 402 403 await storage.setSharedMessageImpressions("test_message", [123, 456]); 404 405 assert.calledOnce(mockConnection.executeCached); 406 const executeCall = mockConnection.executeCached.getCall(0); 407 408 assert.match( 409 executeCall.args[0], 410 /INSERT INTO MessagingSystemMessageImpressions/ 411 ); 412 assert.match(executeCall.args[0], /ON CONFLICT \(messageId\) DO UPDATE/); 413 414 assert.deepEqual(executeCall.args[1], { 415 messageId: "test_message", 416 impressions: JSON.stringify([123, 456]), 417 }); 418 }); 419 420 it("should still create a record if the array is empty", async () => { 421 mockConnection.executeCached.resolves(); 422 423 await storage.setSharedMessageImpressions("test_message", []); 424 425 assert.calledOnce(mockConnection.executeCached); 426 let executeCall = mockConnection.executeCached.getCall(0); 427 assert.match( 428 executeCall.args[0], 429 /INSERT INTO MessagingSystemMessageImpressions/ 430 ); 431 assert.deepEqual(executeCall.args[1], { 432 messageId: "test_message", 433 impressions: JSON.stringify([]), 434 }); 435 }); 436 437 it("should delete the record when impressions is falsy", async () => { 438 mockConnection.executeCached.resolves(); 439 440 await storage.setSharedMessageImpressions("test_message", null); 441 442 assert.calledOnce(mockConnection.executeCached); 443 let executeCall = mockConnection.executeCached.getCall(0); 444 assert.match( 445 executeCall.args[0], 446 /DELETE FROM MessagingSystemMessageImpressions/ 447 ); 448 }); 449 450 it("should call ProfilesDatastoreService.notify() after successful operation", async () => { 451 mockConnection.executeCached.resolves(); 452 453 const notifySpy = sandbox.spy(); 454 455 overrider.set({ 456 ProfilesDatastoreService: { 457 getConnection: sandbox.stub().resolves(mockConnection), 458 notify: notifySpy, 459 }, 460 }); 461 462 await storage.setSharedMessageImpressions("test_message", [123]); 463 assert.calledOnce(notifySpy); 464 }); 465 466 it("should return false when getConnection throws an error", async () => { 467 const connectionError = new Error("Failed to get database connection"); 468 469 overrider.set({ 470 ASRouterPreferences: { 471 console: { error: errorStub }, 472 }, 473 ProfilesDatastoreService: { 474 getConnection: sandbox.stub().rejects(connectionError), 475 notify: sandbox.stub(), 476 }, 477 }); 478 479 const result = await storage.setSharedMessageImpressions( 480 "test_message", 481 [123, 456] 482 ); 483 484 assert.equal(result, false); 485 assert.calledOnce(errorStub); 486 assert.calledWith( 487 errorStub, 488 "ASRouterStorage: Failed writing to MessagingSystemMessageImpressions", 489 connectionError 490 ); 491 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 492 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 493 event: "SHARED_DB_WRITE_FAILED", 494 }); 495 }); 496 497 it("should return false when getConnection returns null", async () => { 498 overrider.set({ 499 ProfilesDatastoreService: { 500 getConnection: sandbox.stub().resolves(null), 501 notify: sandbox.stub(), 502 }, 503 }); 504 505 const result = await storage.setSharedMessageImpressions( 506 "test_message", 507 [123, 456] 508 ); 509 510 assert.equal(result, false); 511 }); 512 }); 513 514 describe("#getSharedMessageBlocklist", () => { 515 it("should return array of blocked message IDs when records exist", async () => { 516 const mockRows = [ 517 { 518 getResultByName: columnName => { 519 if (columnName === "messageId") { 520 return "blocked_message1"; 521 } 522 return null; 523 }, 524 }, 525 { 526 getResultByName: columnName => { 527 if (columnName === "messageId") { 528 return "blocked_message2"; 529 } 530 return null; 531 }, 532 }, 533 ]; 534 535 mockConnection.executeCached.resolves(mockRows); 536 537 const result = await storage.getSharedMessageBlocklist(); 538 539 // Execute should be called with expected SQL 540 assert.calledOnce(mockConnection.executeCached); 541 assert.calledWith( 542 mockConnection.executeCached, 543 "SELECT messageId FROM MessagingSystemMessageBlocklist;" 544 ); 545 546 assert.deepEqual(result, ["blocked_message1", "blocked_message2"]); 547 }); 548 549 it("should return empty array when no blocked messages exist", async () => { 550 mockConnection.executeCached.resolves([]); 551 552 const result = await storage.getSharedMessageBlocklist(); 553 554 assert.deepEqual(result, []); 555 }); 556 557 it("should handle database errors and return null", async () => { 558 const error = new Error("Database connection failed"); 559 mockConnection.executeCached.rejects(error); 560 561 const result = await storage.getSharedMessageBlocklist(); 562 563 assert.equal(result, null); 564 assert.calledOnce(errorStub); 565 assert.calledWith( 566 errorStub, 567 "ASRouterStorage: Failed reading from MessagingSystemMessageBlocklist", 568 error 569 ); 570 571 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 572 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 573 event: "SHARED_DB_READ_FAILED", 574 }); 575 }); 576 577 it("should return null when getConnection throws an error", async () => { 578 const connectionError = new Error("Failed to get database connection"); 579 580 overrider.set({ 581 ASRouterPreferences: { 582 console: { error: errorStub }, 583 }, 584 ProfilesDatastoreService: { 585 getConnection: sandbox.stub().rejects(connectionError), 586 notify: sandbox.stub(), 587 }, 588 }); 589 590 const result = await storage.getSharedMessageBlocklist(); 591 592 assert.equal(result, null); 593 assert.calledOnce(errorStub); 594 assert.calledWith( 595 errorStub, 596 "ASRouterStorage: Failed reading from MessagingSystemMessageBlocklist", 597 connectionError 598 ); 599 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 600 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 601 event: "SHARED_DB_READ_FAILED", 602 }); 603 }); 604 605 it("should return null when getConnection returns null", async () => { 606 overrider.set({ 607 ProfilesDatastoreService: { 608 getConnection: sandbox.stub().resolves(null), 609 notify: sandbox.stub(), 610 }, 611 }); 612 613 const result = await storage.getSharedMessageBlocklist(); 614 615 assert.equal(result, null); 616 }); 617 }); 618 619 describe("#setSharedMessageBlocked", () => { 620 it("should return true success state when blocking a message succeeds", async () => { 621 mockConnection.executeCached.resolves(); 622 623 const result = await storage.setSharedMessageBlocked( 624 "test_message", 625 true 626 ); 627 628 assert.equal(result, true); 629 assert.calledOnce(mockConnection.executeTransaction); 630 }); 631 632 it("should return false success state when the transaction fails", async () => { 633 const error = new Error("Database write failed"); 634 mockConnection.executeCached 635 .withArgs(sinon.match(/INSERT/)) 636 .rejects(error); 637 638 const result = await storage.setSharedMessageBlocked( 639 "test_message", 640 true 641 ); 642 643 assert.equal(result, false); 644 assert.calledOnce(errorStub); 645 assert.calledWith( 646 errorStub, 647 "ASRouterStorage: Failed writing to MessagingSystemMessageBlocklist", 648 error 649 ); 650 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 651 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 652 event: "SHARED_DB_WRITE_FAILED", 653 }); 654 }); 655 656 it("should execute INSERT and DELETE queries in a transaction when blocking a message", async () => { 657 const messageId = "test_blocking_message"; 658 mockConnection.executeCached.resolves(); 659 await storage.setSharedMessageBlocked(messageId, true); 660 661 assertMessageBlockedTransaction(mockConnection, messageId); 662 }); 663 664 it("should execute DELETE query when unblocking a message", async () => { 665 mockConnection.executeCached.resolves(); 666 667 await storage.setSharedMessageBlocked("test_unblocking_message", false); 668 669 assert.calledOnce(mockConnection.executeCached); 670 const executeCall = mockConnection.executeCached.getCall(0); 671 assert.match( 672 executeCall.args[0], 673 /DELETE FROM MessagingSystemMessageBlocklist/ 674 ); 675 assert.deepEqual(executeCall.args[1], { 676 messageId: "test_unblocking_message", 677 }); 678 }); 679 680 it("should default to blocking when isBlocked parameter is not provided", async () => { 681 const messageId = "default_blocked_message"; 682 mockConnection.executeCached.resolves(); 683 684 await storage.setSharedMessageBlocked(messageId); 685 686 assertMessageBlockedTransaction(mockConnection, messageId); 687 }); 688 689 it("should call ProfilesDatastoreService.notify() after successful operation", async () => { 690 mockConnection.executeCached.resolves(); 691 692 const notifySpy = sandbox.spy(); 693 694 overrider.set({ 695 ProfilesDatastoreService: { 696 getConnection: sandbox.stub().resolves(mockConnection), 697 notify: notifySpy, 698 }, 699 }); 700 701 await storage.setSharedMessageBlocked("test_message", true); 702 assert.calledOnce(notifySpy); 703 }); 704 705 it("should return false when getConnection throws an error when blocking a message", async () => { 706 const connectionError = new Error("Failed to get database connection"); 707 708 overrider.set({ 709 ASRouterPreferences: { 710 console: { error: errorStub }, 711 }, 712 ProfilesDatastoreService: { 713 getConnection: sandbox.stub().rejects(connectionError), 714 notify: sandbox.stub(), 715 }, 716 }); 717 718 const result = await storage.setSharedMessageBlocked( 719 "test_message", 720 true 721 ); 722 723 assert.equal(result, false); 724 assert.calledOnce(errorStub); 725 assert.calledWith( 726 errorStub, 727 "ASRouterStorage: Failed writing to MessagingSystemMessageBlocklist", 728 connectionError 729 ); 730 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 731 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 732 event: "SHARED_DB_WRITE_FAILED", 733 }); 734 }); 735 736 it("should return false when getConnection throws an error when unblocking a message", async () => { 737 const connectionError = new Error("Failed to get database connection"); 738 739 overrider.set({ 740 ASRouterPreferences: { 741 console: { error: errorStub }, 742 }, 743 ProfilesDatastoreService: { 744 getConnection: sandbox.stub().rejects(connectionError), 745 notify: sandbox.stub(), 746 }, 747 }); 748 749 const result = await storage.setSharedMessageBlocked( 750 "test_message", 751 false 752 ); 753 754 assert.equal(result, false); 755 assert.calledOnce(errorStub); 756 assert.calledWith( 757 errorStub, 758 "ASRouterStorage: Failed writing to MessagingSystemMessageBlocklist", 759 connectionError 760 ); 761 assert.calledOnce(storage.telemetry.handleUndesiredEvent); 762 assert.calledWith(storage.telemetry.handleUndesiredEvent, { 763 event: "SHARED_DB_WRITE_FAILED", 764 }); 765 }); 766 767 it("should return false when getConnection returns null when blocking a mesasge", async () => { 768 overrider.set({ 769 ProfilesDatastoreService: { 770 getConnection: sandbox.stub().resolves(null), 771 notify: sandbox.stub(), 772 }, 773 }); 774 775 const result = await storage.setSharedMessageBlocked( 776 "test_message", 777 true 778 ); 779 780 assert.equal(result, false); 781 }); 782 783 it("should return false when getConnection returns null when unblokcing a message", async () => { 784 overrider.set({ 785 ProfilesDatastoreService: { 786 getConnection: sandbox.stub().resolves(null), 787 notify: sandbox.stub(), 788 }, 789 }); 790 791 const result = await storage.setSharedMessageBlocked( 792 "test_message", 793 false 794 ); 795 796 assert.equal(result, false); 797 }); 798 }); 799 });