messages.test.js (47710B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 "use strict"; 4 5 const { 6 getAllMessagesUiById, 7 getAllCssMessagesMatchingElements, 8 getAllNetworkMessagesUpdateById, 9 getAllRepeatById, 10 getAllDisabledMessagesById, 11 getCurrentGroup, 12 getGroupsById, 13 getMutableMessagesById, 14 getVisibleMessages, 15 } = require("resource://devtools/client/webconsole/selectors/messages.js"); 16 17 const { 18 clonePacket, 19 getFirstMessage, 20 getLastMessage, 21 getMessageAt, 22 setupActions, 23 setupStore, 24 } = require("resource://devtools/client/webconsole/test/node/helpers.js"); 25 const { 26 stubPackets, 27 stubPreparedMessages, 28 } = require("resource://devtools/client/webconsole/test/node/fixtures/stubs/index.js"); 29 const { 30 MESSAGE_TYPE, 31 CSS_MESSAGE_ADD_MATCHING_ELEMENTS, 32 } = require("resource://devtools/client/webconsole/constants.js"); 33 const { 34 createWarningGroupMessage, 35 } = require("resource://devtools/client/webconsole/utils/messages.js"); 36 37 const expect = require("expect"); 38 39 describe("Message reducer:", () => { 40 let actions; 41 42 beforeAll(() => { 43 actions = setupActions(); 44 }); 45 46 describe("mutableMessagesById", () => { 47 it("adds a message to an empty store", () => { 48 const { dispatch, getState } = setupStore(); 49 50 const packet = stubPackets.get("console.log('foobar', 'test')"); 51 dispatch(actions.messagesAdd([packet])); 52 53 const message = stubPreparedMessages.get("console.log('foobar', 'test')"); 54 55 expect(getFirstMessage(getState())).toEqual(message); 56 }); 57 58 it("increments repeat on a repeating log message", () => { 59 const key1 = "console.log('foobar', 'test')"; 60 const { dispatch, getState } = setupStore([key1, key1], { actions }); 61 62 const packet = clonePacket(stubPackets.get(key1)); 63 const packet2 = clonePacket(packet); 64 65 // Repeat ID must be the same even if the timestamp is different. 66 packet.timeStamp += 1; 67 packet2.timeStamp += 2; 68 dispatch(actions.messagesAdd([packet, packet2])); 69 70 let messages = getMutableMessagesById(getState()); 71 72 expect(messages.size).toBe(1); 73 let repeat = getAllRepeatById(getState()); 74 expect(Object.keys(repeat).length).toBe(1); 75 expect(repeat[getFirstMessage(getState()).id]).toBe(4); 76 77 // Disable repeating messages 78 dispatch(actions.groupSimilarMessagesToggle()); 79 const packet3 = clonePacket(packet); 80 const packet4 = clonePacket(packet); 81 packet3.timeStamp += 3; 82 packet4.timeStamp += 4; 83 dispatch(actions.messagesAdd([packet3, packet4])); 84 85 messages = getMutableMessagesById(getState()); 86 // The 2 new messages were properly added 87 expect(messages.size).toBe(3); 88 repeat = getAllRepeatById(getState()); 89 // repeat didn't changed 90 expect(Object.keys(repeat).length).toBe(1); 91 expect(repeat[getFirstMessage(getState()).id]).toBe(4); 92 93 // Re-enable repeating messages 94 dispatch(actions.groupSimilarMessagesToggle()); 95 const packet5 = clonePacket(packet); 96 const packet6 = clonePacket(packet); 97 packet3.timeStamp += 5; 98 packet4.timeStamp += 6; 99 dispatch(actions.messagesAdd([packet5, packet6])); 100 101 messages = getMutableMessagesById(getState()); 102 // The 2 new messages weren't added, we still have 3 messages 103 expect(messages.size).toBe(3); 104 repeat = getAllRepeatById(getState()); 105 // we now have 2 items in repeat 106 expect(Object.keys(repeat).length).toBe(2); 107 // the first one didn't change 108 expect(repeat[getFirstMessage(getState()).id]).toBe(4); 109 // another one was added for packet4, which is repeated 3 times (packet4, packet5 and packet6) 110 expect(repeat[getLastMessage(getState()).id]).toBe(3); 111 }); 112 113 it("doesn't increment repeat on same log message with different locations", () => { 114 const key1 = "console.log('foobar', 'test')"; 115 const { dispatch, getState } = setupStore(); 116 117 const packet = clonePacket(stubPackets.get(key1)); 118 119 // Dispatch original packet. 120 dispatch(actions.messagesAdd([packet])); 121 122 // Dispatch same packet with modified column number. 123 packet.columnNumber = packet.columnNumber + 1; 124 dispatch(actions.messagesAdd([packet])); 125 126 // Dispatch same packet with modified line number. 127 packet.lineNumber = packet.lineNumber + 1; 128 dispatch(actions.messagesAdd([packet])); 129 130 const messages = getMutableMessagesById(getState()); 131 132 expect(messages.size).toBe(3); 133 134 const repeat = getAllRepeatById(getState()); 135 expect(Object.keys(repeat).length).toBe(0); 136 }); 137 138 it("increments repeat on a repeating css message", () => { 139 const key1 = 140 "Unknown property ‘such-unknown-property’. Declaration dropped."; 141 const { dispatch, getState } = setupStore([key1, key1]); 142 143 const packet = clonePacket(stubPackets.get(key1)); 144 145 // Repeat ID must be the same even if the timestamp is different. 146 packet.pageError.timeStamp = 1; 147 dispatch(actions.messagesAdd([packet])); 148 packet.pageError.timeStamp = 2; 149 dispatch(actions.messagesAdd([packet])); 150 151 const messages = getMutableMessagesById(getState()); 152 153 expect(messages.size).toBe(1); 154 155 const repeat = getAllRepeatById(getState()); 156 expect(repeat[getFirstMessage(getState()).id]).toBe(4); 157 }); 158 159 it("doesn't increment repeat on same css message with different locations", () => { 160 const key1 = 161 "Unknown property ‘such-unknown-property’. Declaration dropped."; 162 const { dispatch, getState } = setupStore(); 163 164 const packet = clonePacket(stubPackets.get(key1)); 165 166 // Dispatch original packet. 167 dispatch(actions.messagesAdd([packet])); 168 169 // Dispatch same packet with modified column number. 170 packet.pageError.columnNumber = packet.pageError.columnNumber + 1; 171 dispatch(actions.messagesAdd([packet])); 172 173 // Dispatch same packet with modified line number. 174 packet.pageError.lineNumber = packet.pageError.lineNumber + 1; 175 dispatch(actions.messagesAdd([packet])); 176 177 const messages = getMutableMessagesById(getState()); 178 179 expect(messages.size).toBe(3); 180 181 const repeat = getAllRepeatById(getState()); 182 expect(Object.keys(repeat).length).toBe(0); 183 }); 184 185 it("increments repeat on a repeating error message", () => { 186 const key1 = "ReferenceError: asdf is not defined"; 187 const { dispatch, getState } = setupStore([key1, key1]); 188 189 const packet = clonePacket(stubPackets.get(key1)); 190 191 // Repeat ID must be the same even if the timestamp is different. 192 packet.pageError.timeStamp = 1; 193 dispatch(actions.messagesAdd([packet])); 194 packet.pageError.timeStamp = 2; 195 dispatch(actions.messagesAdd([packet])); 196 197 const messages = getMutableMessagesById(getState()); 198 199 expect(messages.size).toBe(1); 200 201 const repeat = getAllRepeatById(getState()); 202 expect(repeat[getFirstMessage(getState()).id]).toBe(4); 203 }); 204 205 it("does not increment repeat after closing a group", () => { 206 const logKey = "console.log('foobar', 'test')"; 207 const { getState } = setupStore([ 208 logKey, 209 logKey, 210 "console.group('bar')", 211 logKey, 212 logKey, 213 logKey, 214 "console.groupEnd()", 215 logKey, 216 ]); 217 218 const messages = getMutableMessagesById(getState()); 219 220 expect(messages.size).toBe(4); 221 const repeat = getAllRepeatById(getState()); 222 expect(repeat[getFirstMessage(getState()).id]).toBe(2); 223 expect(repeat[getMessageAt(getState(), 2).id]).toBe(3); 224 expect(repeat[getLastMessage(getState()).id]).toBe(undefined); 225 }); 226 227 it("doesn't increment undefined messages coming from different places", () => { 228 const { getState } = setupStore(["console.log(undefined)", "undefined"]); 229 230 const messages = getMutableMessagesById(getState()); 231 expect(messages.size).toBe(2); 232 233 const repeat = getAllRepeatById(getState()); 234 expect(Object.keys(repeat).length).toBe(0); 235 }); 236 237 it("doesn't increment successive falsy but different messages", () => { 238 const { getState } = setupStore( 239 ["console.log(NaN)", "console.log(undefined)", "console.log(null)"], 240 { actions } 241 ); 242 243 const messages = getMutableMessagesById(getState()); 244 expect(messages.size).toBe(3); 245 const repeat = getAllRepeatById(getState()); 246 expect(Object.keys(repeat).length).toBe(0); 247 }); 248 249 it("increment falsy messages when expected", () => { 250 const { dispatch, getState } = setupStore(); 251 252 const nanPacket = stubPackets.get("console.log(NaN)"); 253 dispatch(actions.messagesAdd([nanPacket, nanPacket])); 254 let messages = getMutableMessagesById(getState()); 255 expect(messages.size).toBe(1); 256 let repeat = getAllRepeatById(getState()); 257 expect(repeat[getLastMessage(getState()).id]).toBe(2); 258 259 const undefinedPacket = stubPackets.get("console.log(undefined)"); 260 dispatch(actions.messagesAdd([undefinedPacket, undefinedPacket])); 261 messages = getMutableMessagesById(getState()); 262 expect(messages.size).toBe(2); 263 repeat = getAllRepeatById(getState()); 264 expect(repeat[getLastMessage(getState()).id]).toBe(2); 265 266 const nullPacket = stubPackets.get("console.log(null)"); 267 dispatch(actions.messagesAdd([nullPacket, nullPacket])); 268 messages = getMutableMessagesById(getState()); 269 expect(messages.size).toBe(3); 270 repeat = getAllRepeatById(getState()); 271 expect(repeat[getLastMessage(getState()).id]).toBe(2); 272 }); 273 274 it("does not clobber a unique message", () => { 275 const key1 = "console.log('foobar', 'test')"; 276 const { dispatch, getState } = setupStore([key1, key1]); 277 278 const packet = stubPackets.get(key1); 279 dispatch(actions.messagesAdd([packet])); 280 281 const packet2 = stubPackets.get("console.log(undefined)"); 282 dispatch(actions.messagesAdd([packet2])); 283 284 const messages = getMutableMessagesById(getState()); 285 expect(messages.size).toBe(2); 286 287 const repeat = getAllRepeatById(getState()); 288 expect(repeat[getFirstMessage(getState()).id]).toBe(3); 289 expect(repeat[getLastMessage(getState()).id]).toBe(undefined); 290 }); 291 292 it("does not increment repeat after adding similar warning group", () => { 293 const { dispatch, getState } = setupStore(); 294 295 // Mocking a warning message that would create a warning group 296 const warningMessage = stubPreparedMessages.get( 297 "ReferenceError: asdf is not defined" 298 ); 299 warningMessage.messageText = 300 "The resource at “https://evil.com” was blocked."; 301 warningMessage.category = "cookieBlockedPermission"; 302 303 const type = MESSAGE_TYPE.CONTENT_BLOCKING_GROUP; 304 const firstMessageId = `${warningMessage.type}-${warningMessage.innerWindowID}`; 305 const message1 = createWarningGroupMessage( 306 firstMessageId, 307 type, 308 warningMessage 309 ); 310 const secondMessageId = `${warningMessage.type}-${ 311 warningMessage.innerWindowID + 10 312 }`; 313 const message2 = createWarningGroupMessage( 314 secondMessageId, 315 type, 316 warningMessage 317 ); 318 319 dispatch(actions.messagesAdd([message1, message2])); 320 321 const messages = getMutableMessagesById(getState()); 322 expect(messages.size).toBe(2); 323 324 const repeat = getAllRepeatById(getState()); 325 expect(Object.keys(repeat).length).toBe(0); 326 }); 327 328 it("does not increment repeat after adding different Symbols", () => { 329 const { getState } = setupStore([ 330 "console.log(Symbol.for('foo'))", 331 "console.log(Symbol.for('bar'))", 332 ]); 333 334 const repeat = getAllRepeatById(getState()); 335 expect(Object.keys(repeat).length).toBe(0); 336 }); 337 338 it("adds a message in response to console.clear()", () => { 339 const { dispatch, getState } = setupStore([]); 340 341 dispatch(actions.messagesAdd([stubPackets.get("console.clear()")])); 342 343 const messages = getMutableMessagesById(getState()); 344 345 expect(messages.size).toBe(1); 346 expect(getFirstMessage(getState()).parameters[0]).toBe( 347 "Console was cleared." 348 ); 349 }); 350 351 it("clears the messages list in response to MESSAGES_CLEAR action", () => { 352 const { dispatch, getState } = setupStore([ 353 "console.log('foobar', 'test')", 354 "console.log('foobar', 'test')", 355 "console.log(undefined)", 356 "console.table(['red', 'green', 'blue']);", 357 "console.group('bar')", 358 ]); 359 360 dispatch(actions.messagesClear()); 361 362 const state = getState(); 363 expect(getMutableMessagesById(state).size).toBe(0); 364 expect(getVisibleMessages(state).length).toBe(0); 365 expect(getAllMessagesUiById(state).length).toBe(0); 366 expect(getGroupsById(state).size).toBe(0); 367 expect(getAllCssMessagesMatchingElements(state).size).toBe(0); 368 expect(getCurrentGroup(state)).toBe(null); 369 expect(getAllRepeatById(state)).toEqual({}); 370 expect(state.messages.mutableMessagesOrder).toEqual([]); 371 }); 372 373 it("cleans the repeatsById object when messages are pruned", () => { 374 const { dispatch, getState } = setupStore( 375 [ 376 "console.log('foobar', 'test')", 377 "console.log('foobar', 'test')", 378 "console.log(undefined)", 379 "console.log(undefined)", 380 ], 381 { 382 actions, 383 storeOptions: { 384 logLimit: 2, 385 }, 386 } 387 ); 388 389 // Check that we have the expected data. 390 let repeats = getAllRepeatById(getState()); 391 expect(Object.keys(repeats).length).toBe(2); 392 const lastMessageId = getLastMessage(getState()).id; 393 394 // This addition will prune the first message out of the store. 395 let packet = stubPackets.get("console.log('foobar', 'test')"); 396 dispatch(actions.messagesAdd([packet])); 397 398 repeats = getAllRepeatById(getState()); 399 400 // There should be only the data for the "undefined" message. 401 expect(Object.keys(repeats)).toEqual([lastMessageId]); 402 expect(Object.keys(repeats).length).toBe(1); 403 expect(repeats[lastMessageId]).toBe(2); 404 405 // This addition will prune the first message out of the store. 406 packet = stubPackets.get("console.log(undefined)"); 407 dispatch(actions.messagesAdd([packet])); 408 409 // repeatById should now be empty. 410 expect(getAllRepeatById(getState())).toEqual({}); 411 }); 412 413 it("properly limits number of messages", () => { 414 const logLimit = 1000; 415 const { dispatch, getState } = setupStore([], { 416 storeOptions: { 417 logLimit, 418 }, 419 }); 420 421 const packet = clonePacket(stubPackets.get("console.log(undefined)")); 422 423 for (let i = 1; i <= logLimit + 2; i++) { 424 packet.arguments = [`message num ${i}`]; 425 dispatch(actions.messagesAdd([packet])); 426 } 427 428 const messages = getMutableMessagesById(getState()); 429 expect(messages.size).toBe(logLimit); 430 expect(getFirstMessage(getState()).parameters[0]).toBe(`message num 3`); 431 expect(getLastMessage(getState()).parameters[0]).toBe( 432 `message num ${logLimit + 2}` 433 ); 434 435 const { mutableMessagesOrder } = getState().messages; 436 expect(mutableMessagesOrder.length).toBe(logLimit); 437 }); 438 439 it("properly limits number of messages when there are nested groups", () => { 440 const logLimit = 1000; 441 const { dispatch, getState } = setupStore([], { 442 storeOptions: { 443 logLimit, 444 }, 445 }); 446 447 const packet = clonePacket(stubPackets.get("console.log(undefined)")); 448 const packetGroup = clonePacket(stubPackets.get("console.group('bar')")); 449 const packetGroupEnd = clonePacket(stubPackets.get("console.groupEnd()")); 450 451 packetGroup.arguments = [`group-1`]; 452 dispatch(actions.messagesAdd([packetGroup])); 453 packetGroup.arguments = [`group-1-1`]; 454 dispatch(actions.messagesAdd([packetGroup])); 455 packetGroup.arguments = [`group-1-1-1`]; 456 dispatch(actions.messagesAdd([packetGroup])); 457 packet.arguments = [`message-in-group-1`]; 458 dispatch(actions.messagesAdd([packet])); 459 packet.arguments = [`message-in-group-2`]; 460 dispatch(actions.messagesAdd([packet])); 461 // Closing group-1-1-1 462 dispatch(actions.messagesAdd([packetGroupEnd])); 463 // Closing group-1-1 464 dispatch(actions.messagesAdd([packetGroupEnd])); 465 // Closing group-1 466 dispatch(actions.messagesAdd([packetGroupEnd])); 467 468 for (let i = 0; i < logLimit; i++) { 469 packet.arguments = [`message-${i}`]; 470 dispatch(actions.messagesAdd([packet])); 471 } 472 473 const visibleMessages = getVisibleMessages(getState()); 474 const messages = getMutableMessagesById(getState()); 475 const { mutableMessagesOrder } = getState().messages; 476 477 expect(messages.size).toBe(logLimit); 478 expect(visibleMessages.length).toBe(logLimit); 479 expect(mutableMessagesOrder.length).toBe(logLimit); 480 481 expect(messages.get(visibleMessages[0]).parameters[0]).toBe(`message-0`); 482 expect(messages.get(visibleMessages[logLimit - 1]).parameters[0]).toBe( 483 `message-${logLimit - 1}` 484 ); 485 486 // The groups were cleaned up. 487 const groups = getGroupsById(getState()); 488 expect(groups.size).toBe(0); 489 }); 490 491 it("properly limits number of groups", () => { 492 const logLimit = 100; 493 const { dispatch, getState } = setupStore([], { 494 storeOptions: { logLimit }, 495 }); 496 497 const packet = clonePacket(stubPackets.get("console.log(undefined)")); 498 const packetGroup = clonePacket(stubPackets.get("console.group('bar')")); 499 const packetGroupEnd = clonePacket(stubPackets.get("console.groupEnd()")); 500 501 for (let i = 0; i < logLimit + 2; i++) { 502 dispatch(actions.messagesAdd([packetGroup])); 503 packet.arguments = [`message-${i}-a`]; 504 dispatch(actions.messagesAdd([packet])); 505 packet.arguments = [`message-${i}-b`]; 506 dispatch(actions.messagesAdd([packet])); 507 dispatch(actions.messagesAdd([packetGroupEnd])); 508 } 509 510 const visibleMessages = getVisibleMessages(getState()); 511 const messages = getMutableMessagesById(getState()); 512 // We should have three times the logLimit since each group has one message inside. 513 expect(messages.size).toBe(logLimit * 3); 514 515 // We should have logLimit number of groups 516 const groups = getGroupsById(getState()); 517 expect(groups.size).toBe(logLimit); 518 519 expect(messages.get(visibleMessages[1]).parameters[0]).toBe( 520 `message-2-a` 521 ); 522 expect(getLastMessage(getState()).parameters[0]).toBe( 523 `message-${logLimit + 1}-b` 524 ); 525 }); 526 527 it("properly limits number of collapsed groups", () => { 528 const logLimit = 100; 529 const { dispatch, getState } = setupStore([], { 530 storeOptions: { logLimit }, 531 }); 532 533 const packet = clonePacket(stubPackets.get("console.log(undefined)")); 534 const packetGroupCollapsed = clonePacket( 535 stubPackets.get("console.groupCollapsed('foo')") 536 ); 537 const packetGroupEnd = clonePacket(stubPackets.get("console.groupEnd()")); 538 539 for (let i = 0; i < logLimit + 2; i++) { 540 packetGroupCollapsed.arguments = [`group-${i}`]; 541 dispatch(actions.messagesAdd([packetGroupCollapsed])); 542 packet.arguments = [`message-${i}-a`]; 543 dispatch(actions.messagesAdd([packet])); 544 packet.arguments = [`message-${i}-b`]; 545 dispatch(actions.messagesAdd([packet])); 546 dispatch(actions.messagesAdd([packetGroupEnd])); 547 } 548 549 const messages = getMutableMessagesById(getState()); 550 // We should have three times the logLimit since each group has two message inside. 551 expect(messages.size).toBe(logLimit * 3); 552 553 // We should have logLimit number of groups 554 const groups = getGroupsById(getState()); 555 expect(groups.size).toBe(logLimit); 556 557 expect(getFirstMessage(getState()).parameters[0]).toBe(`group-2`); 558 expect(getLastMessage(getState()).parameters[0]).toBe( 559 `message-${logLimit + 1}-b` 560 ); 561 562 const visibleMessages = getVisibleMessages(getState()); 563 expect(visibleMessages.length).toBe(logLimit); 564 const lastVisibleMessageId = visibleMessages[visibleMessages.length - 1]; 565 expect(messages.get(lastVisibleMessageId).parameters[0]).toBe( 566 `group-${logLimit + 1}` 567 ); 568 }); 569 570 it("does not add null messages to the store", () => { 571 const { dispatch, getState } = setupStore(); 572 573 const message = stubPackets.get("console.time('bar')"); 574 dispatch(actions.messagesAdd([message])); 575 576 const messages = getMutableMessagesById(getState()); 577 expect(messages.size).toBe(0); 578 }); 579 580 it("adds console.table call with unsupported type as console.log", () => { 581 const { dispatch, getState } = setupStore(); 582 583 const packet = stubPackets.get("console.table('bar')"); 584 dispatch(actions.messagesAdd([packet])); 585 586 const tableMessage = getLastMessage(getState()); 587 expect(tableMessage.level).toEqual(MESSAGE_TYPE.LOG); 588 }); 589 590 it("adds console.group messages to the store", () => { 591 const { dispatch, getState } = setupStore(); 592 593 const message = stubPackets.get("console.group('bar')"); 594 dispatch(actions.messagesAdd([message])); 595 596 const messages = getMutableMessagesById(getState()); 597 expect(messages.size).toBe(1); 598 }); 599 600 it("adds messages in console.group to the store", () => { 601 const { dispatch, getState } = setupStore(); 602 603 const groupPacket = stubPackets.get("console.group('bar')"); 604 const groupEndPacket = stubPackets.get("console.groupEnd('bar')"); 605 const logPacket = stubPackets.get("console.log('foobar', 'test')"); 606 607 const packets = [ 608 groupPacket, 609 logPacket, 610 groupPacket, 611 groupPacket, 612 logPacket, 613 groupEndPacket, 614 logPacket, 615 groupEndPacket, 616 logPacket, 617 groupEndPacket, 618 logPacket, 619 ]; 620 dispatch(actions.messagesAdd(packets)); 621 622 // Here is what we should have (8 messages) 623 // ▼ bar 624 // | foobar test 625 // | ▼ bar 626 // | | ▼ bar 627 // | | | foobar test 628 // | | foobar test 629 // | foobar test 630 // foobar test 631 632 const isNotGroupEnd = p => p !== groupEndPacket; 633 const messageCount = packets.filter(isNotGroupEnd).length; 634 635 const messages = getMutableMessagesById(getState()); 636 const visibleMessages = getVisibleMessages(getState()); 637 expect(messages.size).toBe(messageCount); 638 expect(visibleMessages.length).toBe(messageCount); 639 }); 640 641 it("sets groupId property as expected", () => { 642 const { dispatch, getState } = setupStore(); 643 644 dispatch( 645 actions.messagesAdd([ 646 stubPackets.get("console.group('bar')"), 647 stubPackets.get("console.log('foobar', 'test')"), 648 ]) 649 ); 650 651 const messages = getMutableMessagesById(getState()); 652 expect(messages.size).toBe(2); 653 expect(getLastMessage(getState()).groupId).toBe( 654 getFirstMessage(getState()).id 655 ); 656 }); 657 658 it("does not display console.groupEnd messages to the store", () => { 659 const { dispatch, getState } = setupStore(); 660 661 const message = stubPackets.get("console.groupEnd('bar')"); 662 dispatch(actions.messagesAdd([message])); 663 664 const messages = getMutableMessagesById(getState()); 665 expect(messages.size).toBe(0); 666 }); 667 668 it("filters out message added after a console.groupCollapsed message", () => { 669 const { dispatch, getState } = setupStore(); 670 671 dispatch( 672 actions.messagesAdd([ 673 stubPackets.get("console.groupCollapsed('foo')"), 674 stubPackets.get("console.log('foobar', 'test')"), 675 ]) 676 ); 677 678 const messages = getVisibleMessages(getState()); 679 expect(messages.length).toBe(1); 680 }); 681 682 it("adds console.dirxml call as console.log", () => { 683 const { dispatch, getState } = setupStore(); 684 685 const packet = stubPackets.get("console.dirxml(window)"); 686 dispatch(actions.messagesAdd([packet])); 687 688 const dirxmlMessage = getLastMessage(getState()); 689 expect(dirxmlMessage.level).toEqual(MESSAGE_TYPE.LOG); 690 }); 691 692 it("does not throw when adding incomplete console.count packet", () => { 693 const { dispatch, getState } = setupStore(); 694 const packet = clonePacket(stubPackets.get(`console.count('bar')`)); 695 696 // Remove counter information to mimick packet we receive in the browser console. 697 delete packet.counter; 698 699 dispatch(actions.messagesAdd([packet])); 700 // The message should not be added to the state. 701 expect(getMutableMessagesById(getState()).size).toBe(0); 702 }); 703 }); 704 705 describe("mutableMessagesOrder", () => { 706 it("adds a message to an empty store", () => { 707 const { dispatch, getState } = setupStore(); 708 709 const packet = stubPackets.get("console.log('foobar', 'test')"); 710 dispatch(actions.messagesAdd([packet])); 711 712 const { mutableMessagesOrder } = getState().messages; 713 expect(mutableMessagesOrder.length).toBe(1); 714 expect(mutableMessagesOrder[0]).toBe( 715 // Don't get getMessageIndexAt/getFirstMessage since it relies on mutableMessagesOrder 716 [...getMutableMessagesById(getState()).keys()][0] 717 ); 718 }); 719 720 it("reorder messages", () => { 721 const { dispatch, getState } = setupStore(); 722 723 const naNpacket = stubPackets.get("console.log(NaN)"); 724 dispatch(actions.messagesAdd([naNpacket])); 725 726 // Add a message that has a shorter timestamp than the previous one, and thus, should 727 // be displayed before 728 const nullPacket = clonePacket(stubPackets.get("console.log(null)")); 729 nullPacket.timeStamp = naNpacket.timeStamp - 10; 730 dispatch(actions.messagesAdd([nullPacket])); 731 732 // Add a message that should be display between the 2 previous messages 733 const undefinedPacket = clonePacket( 734 stubPackets.get("console.log(undefined)") 735 ); 736 undefinedPacket.timeStamp = naNpacket.timeStamp - 5; 737 dispatch(actions.messagesAdd([undefinedPacket])); 738 739 const { mutableMessagesOrder } = getState().messages; 740 const [nanMessage, nullMessage, undefinedMessage] = [ 741 ...getMutableMessagesById(getState()).values(), 742 ]; 743 const visibleMessages = getVisibleMessages(getState()); 744 745 // Checking that messages in the Map are the expected ones 746 expect(nanMessage.parameters[0].type).toBe("NaN"); 747 expect(nullMessage.parameters[0].type).toBe("null"); 748 expect(undefinedMessage.parameters[0].type).toBe("undefined"); 749 750 // Check that mutableMessagesOrder has the message ids in the chronological order 751 expect(mutableMessagesOrder).toEqual([ 752 nullMessage.id, 753 undefinedMessage.id, 754 nanMessage.id, 755 ]); 756 757 // Since we didn't filtered anything, visibleMessages should be similar to mutableMessagesOrder 758 expect(mutableMessagesOrder).toEqual(visibleMessages); 759 760 // Check that visibleMessages is computed from mutableMessagesOrder when filtering 761 dispatch(actions.filterToggle("log")); 762 expect(getVisibleMessages(getState())).toEqual([]); 763 dispatch(actions.filterToggle("log")); 764 expect(getVisibleMessages(getState())).toEqual([ 765 nullMessage.id, 766 undefinedMessage.id, 767 nanMessage.id, 768 ]); 769 }); 770 }); 771 772 describe("expandedMessageIds", () => { 773 it("opens console.trace messages when they are added", () => { 774 const { dispatch, getState } = setupStore(); 775 776 const message = stubPackets.get("console.trace()"); 777 dispatch(actions.messagesAdd([message])); 778 779 const expanded = getAllMessagesUiById(getState()); 780 expect(expanded.length).toBe(1); 781 expect(expanded[0]).toBe(getFirstMessage(getState()).id); 782 }); 783 784 it("clears the messages UI list in response to MESSAGES_CLEAR action", () => { 785 const { dispatch, getState } = setupStore([ 786 "console.log('foobar', 'test')", 787 "console.log(undefined)", 788 ]); 789 790 const traceMessage = stubPackets.get("console.trace()"); 791 dispatch(actions.messagesAdd([traceMessage])); 792 793 dispatch(actions.messagesClear()); 794 795 const expanded = getAllMessagesUiById(getState()); 796 expect(expanded.length).toBe(0); 797 }); 798 799 it("cleans the messages UI list when messages are pruned", () => { 800 const { dispatch, getState } = setupStore( 801 ["console.trace()", "console.log(undefined)", "console.trace()"], 802 { 803 storeOptions: { 804 logLimit: 3, 805 }, 806 } 807 ); 808 809 // Check that we have the expected data. 810 let expanded = getAllMessagesUiById(getState()); 811 expect(expanded.length).toBe(2); 812 expect(expanded[0]).toBe(getFirstMessage(getState()).id); 813 const lastMessageId = getLastMessage(getState()).id; 814 expect(expanded[expanded.length - 1]).toBe(lastMessageId); 815 816 // This addition will prune the first message out of the store. 817 let packet = stubPackets.get("console.log(undefined)"); 818 dispatch(actions.messagesAdd([packet])); 819 820 expanded = getAllMessagesUiById(getState()); 821 822 // There should be only the id of the last console.trace message. 823 expect(expanded.length).toBe(1); 824 expect(expanded[0]).toBe(lastMessageId); 825 826 // These additions will prune the last console.trace message out of the store. 827 packet = stubPackets.get("console.log('foobar', 'test')"); 828 dispatch(actions.messagesAdd([packet])); 829 packet = stubPackets.get("console.log(undefined)"); 830 dispatch(actions.messagesAdd([packet])); 831 832 // expandedMessageIds should now be empty. 833 expect(getAllMessagesUiById(getState()).length).toBe(0); 834 }); 835 836 it("opens console.group messages when they are added", () => { 837 const { dispatch, getState } = setupStore(); 838 839 const message = stubPackets.get("console.group('bar')"); 840 dispatch(actions.messagesAdd([message])); 841 842 const expanded = getAllMessagesUiById(getState()); 843 expect(expanded.length).toBe(1); 844 expect(expanded[0]).toBe(getFirstMessage(getState()).id); 845 }); 846 847 it("does not open console.groupCollapsed messages when they are added", () => { 848 const { dispatch, getState } = setupStore(); 849 850 const message = stubPackets.get("console.groupCollapsed('foo')"); 851 dispatch(actions.messagesAdd([message])); 852 853 const expanded = getAllMessagesUiById(getState()); 854 expect(expanded.length).toBe(0); 855 }); 856 857 it("reacts to messageClose/messageOpen actions on console.group", () => { 858 const { dispatch, getState } = setupStore(["console.group('bar')"]); 859 const firstMessageId = getFirstMessage(getState()).id; 860 861 let expanded = getAllMessagesUiById(getState()); 862 expect(expanded.length).toBe(1); 863 expect(expanded[0]).toBe(firstMessageId); 864 865 dispatch(actions.messageClose(firstMessageId)); 866 867 expanded = getAllMessagesUiById(getState()); 868 expect(expanded.length).toBe(0); 869 870 dispatch(actions.messageOpen(firstMessageId)); 871 872 expanded = getAllMessagesUiById(getState()); 873 expect(expanded.length).toBe(1); 874 expect(expanded[0]).toBe(firstMessageId); 875 }); 876 877 it("reacts to messageClose/messageOpen actions on exception", () => { 878 const { dispatch, getState } = setupStore([ 879 "ReferenceError: asdf is not defined", 880 ]); 881 const firstMessageId = getFirstMessage(getState()).id; 882 883 let expanded = getAllMessagesUiById(getState()); 884 expect(expanded.length).toBe(0); 885 886 dispatch(actions.messageOpen(firstMessageId)); 887 888 expanded = getAllMessagesUiById(getState()); 889 expect(expanded.length).toBe(1); 890 expect(expanded[0]).toBe(firstMessageId); 891 892 dispatch(actions.messageClose(firstMessageId)); 893 894 expanded = getAllMessagesUiById(getState()); 895 expect(expanded.length).toBe(0); 896 }); 897 }); 898 899 describe("currentGroup", () => { 900 it("sets the currentGroup when console.group message is added", () => { 901 const { dispatch, getState } = setupStore(); 902 903 const packet = stubPackets.get("console.group('bar')"); 904 dispatch(actions.messagesAdd([packet])); 905 906 const currentGroup = getCurrentGroup(getState()); 907 expect(currentGroup).toBe(getFirstMessage(getState()).id); 908 }); 909 910 it("sets currentGroup to expected value when console.groupEnd is added", () => { 911 const { dispatch, getState } = setupStore([ 912 "console.group('bar')", 913 "console.groupCollapsed('foo')", 914 "console.group('bar')", 915 "console.groupEnd('bar')", 916 ]); 917 918 let currentGroup = getCurrentGroup(getState()); 919 expect(currentGroup).toBe(getMessageAt(getState(), 1).id); 920 921 const endFooPacket = stubPackets.get("console.groupEnd('foo')"); 922 dispatch(actions.messagesAdd([endFooPacket])); 923 currentGroup = getCurrentGroup(getState()); 924 expect(currentGroup).toBe(getFirstMessage(getState()).id); 925 926 const endBarPacket = stubPackets.get("console.groupEnd('bar')"); 927 dispatch(actions.messagesAdd([endBarPacket])); 928 currentGroup = getCurrentGroup(getState()); 929 expect(currentGroup).toBe(null); 930 }); 931 932 it("resets the currentGroup to null in response to MESSAGES_CLEAR action", () => { 933 const { dispatch, getState } = setupStore(["console.group('bar')"]); 934 935 dispatch(actions.messagesClear()); 936 937 const currentGroup = getCurrentGroup(getState()); 938 expect(currentGroup).toBe(null); 939 }); 940 }); 941 942 describe("groupsById", () => { 943 it("adds the group with expected array when console.group message is added", () => { 944 const { dispatch, getState } = setupStore(); 945 946 const barPacket = stubPackets.get("console.group('bar')"); 947 dispatch(actions.messagesAdd([barPacket])); 948 949 let groupsById = getGroupsById(getState()); 950 expect(groupsById.size).toBe(1); 951 expect(groupsById.has(getFirstMessage(getState()).id)).toBe(true); 952 expect(groupsById.get(getFirstMessage(getState()).id)).toEqual([]); 953 954 const fooPacket = stubPackets.get("console.groupCollapsed('foo')"); 955 dispatch(actions.messagesAdd([fooPacket])); 956 957 groupsById = getGroupsById(getState()); 958 expect(groupsById.size).toBe(2); 959 expect(groupsById.has(getLastMessage(getState()).id)).toBe(true); 960 expect(groupsById.get(getLastMessage(getState()).id)).toEqual([ 961 getFirstMessage(getState()).id, 962 ]); 963 }); 964 965 it("resets groupsById in response to MESSAGES_CLEAR action", () => { 966 const { dispatch, getState } = setupStore([ 967 "console.group('bar')", 968 "console.groupCollapsed('foo')", 969 ]); 970 971 let groupsById = getGroupsById(getState()); 972 expect(groupsById.size).toBe(2); 973 974 dispatch(actions.messagesClear()); 975 976 groupsById = getGroupsById(getState()); 977 expect(groupsById.size).toBe(0); 978 }); 979 980 it("cleans the groupsById property when messages are pruned", () => { 981 const { dispatch, getState } = setupStore( 982 [ 983 "console.group('bar')", 984 "console.group()", 985 "console.groupEnd()", 986 "console.groupEnd('bar')", 987 "console.group('bar')", 988 "console.groupEnd('bar')", 989 "console.log('foobar', 'test')", 990 ], 991 { 992 actions, 993 storeOptions: { 994 logLimit: 3, 995 }, 996 } 997 ); 998 999 /* 1000 * Here is the initial state of the console: 1001 * ▶︎ bar 1002 * ▶︎ noLabel 1003 * ▶︎ bar 1004 * foobar test 1005 */ 1006 1007 // Check that we have the expected data. 1008 let groupsById = getGroupsById(getState()); 1009 expect(groupsById.size).toBe(3); 1010 1011 // This addition will prune the first group (and its child group) out of the store. 1012 /* 1013 * ▶︎ bar 1014 * foobar test 1015 * undefined 1016 */ 1017 let packet = stubPackets.get("console.log(undefined)"); 1018 dispatch(actions.messagesAdd([packet])); 1019 1020 groupsById = getGroupsById(getState()); 1021 1022 // There should be only the id of the last console.group message. 1023 expect(groupsById.size).toBe(1); 1024 1025 // This additions will prune the last group message out of the store. 1026 /* 1027 * foobar test 1028 * undefined 1029 * foobar test 1030 */ 1031 packet = stubPackets.get("console.log('foobar', 'test')"); 1032 dispatch(actions.messagesAdd([packet])); 1033 1034 // groupsById should now be empty. 1035 expect(getGroupsById(getState()).size).toBe(0); 1036 }); 1037 }); 1038 1039 describe("networkMessagesUpdateById", () => { 1040 it("adds the network update message when network update action is called", () => { 1041 const { dispatch, getState } = setupStore(); 1042 1043 let packet = clonePacket(stubPackets.get("GET request")); 1044 let updatePacket = clonePacket(stubPackets.get("GET request update")); 1045 1046 packet.actor = "message1"; 1047 updatePacket.actor = "message1"; 1048 dispatch(actions.messagesAdd([packet])); 1049 dispatch(actions.networkMessageUpdates([updatePacket])); 1050 1051 let networkUpdates = getAllNetworkMessagesUpdateById(getState()); 1052 expect(Object.keys(networkUpdates)).toEqual(["message1"]); 1053 1054 packet = clonePacket(stubPackets.get("GET request")); 1055 updatePacket = stubPackets.get("XHR GET request update"); 1056 packet.actor = "message2"; 1057 updatePacket.actor = "message2"; 1058 dispatch(actions.messagesAdd([packet])); 1059 dispatch(actions.networkMessageUpdates([updatePacket])); 1060 1061 networkUpdates = getAllNetworkMessagesUpdateById(getState()); 1062 expect(Object.keys(networkUpdates)).toEqual(["message1", "message2"]); 1063 }); 1064 1065 it("resets networkMessagesUpdateById in response to MESSAGES_CLEAR action", () => { 1066 const { dispatch, getState } = setupStore(["XHR GET request"]); 1067 1068 const updatePacket = stubPackets.get("XHR GET request update"); 1069 dispatch(actions.networkMessageUpdates([updatePacket])); 1070 1071 let networkUpdates = getAllNetworkMessagesUpdateById(getState()); 1072 expect(!!Object.keys(networkUpdates).length).toBe(true); 1073 1074 dispatch(actions.messagesClear()); 1075 1076 networkUpdates = getAllNetworkMessagesUpdateById(getState()); 1077 expect(Object.keys(networkUpdates).length).toBe(0); 1078 }); 1079 1080 it("cleans the networkMessagesUpdateById property when messages are pruned", () => { 1081 const { dispatch, getState } = setupStore([], { 1082 storeOptions: { 1083 logLimit: 3, 1084 }, 1085 }); 1086 1087 // Add 3 network messages and their updates 1088 let packet = clonePacket(stubPackets.get("XHR GET request")); 1089 const updatePacket = clonePacket( 1090 stubPackets.get("XHR GET request update") 1091 ); 1092 packet.actor = "message1"; 1093 updatePacket.actor = "message1"; 1094 dispatch(actions.messagesAdd([packet])); 1095 dispatch(actions.networkMessageUpdates([updatePacket])); 1096 1097 packet.actor = "message2"; 1098 updatePacket.actor = "message2"; 1099 dispatch(actions.messagesAdd([packet])); 1100 dispatch(actions.networkMessageUpdates([updatePacket])); 1101 1102 packet.actor = "message3"; 1103 updatePacket.actor = "message3"; 1104 dispatch(actions.messagesAdd([packet])); 1105 dispatch(actions.networkMessageUpdates([updatePacket])); 1106 1107 // Check that we have the expected data. 1108 const messages = getMutableMessagesById(getState()); 1109 const [ 1110 firstNetworkMessageId, 1111 secondNetworkMessageId, 1112 thirdNetworkMessageId, 1113 ] = [...messages.keys()]; 1114 1115 let networkUpdates = getAllNetworkMessagesUpdateById(getState()); 1116 expect(Object.keys(networkUpdates)).toEqual([ 1117 firstNetworkMessageId, 1118 secondNetworkMessageId, 1119 thirdNetworkMessageId, 1120 ]); 1121 1122 // This addition will remove the first network message. 1123 packet = stubPackets.get("console.log(undefined)"); 1124 dispatch(actions.messagesAdd([packet])); 1125 1126 networkUpdates = getAllNetworkMessagesUpdateById(getState()); 1127 expect(Object.keys(networkUpdates)).toEqual([ 1128 secondNetworkMessageId, 1129 thirdNetworkMessageId, 1130 ]); 1131 1132 // This addition will remove the second network message. 1133 packet = stubPackets.get("console.log('foobar', 'test')"); 1134 dispatch(actions.messagesAdd([packet])); 1135 1136 networkUpdates = getAllNetworkMessagesUpdateById(getState()); 1137 expect(Object.keys(networkUpdates)).toEqual([thirdNetworkMessageId]); 1138 1139 // This addition will remove the last network message. 1140 packet = stubPackets.get("console.log(undefined)"); 1141 dispatch(actions.messagesAdd([packet])); 1142 1143 // networkMessageUpdateById should now be empty. 1144 networkUpdates = getAllNetworkMessagesUpdateById(getState()); 1145 expect(Object.keys(networkUpdates)).toEqual([]); 1146 }); 1147 }); 1148 1149 describe("cssMessagesMatchingElements", () => { 1150 it("resets cssMessagesMatchingElements in response to MESSAGES_CLEAR action", () => { 1151 const { dispatch, getState } = setupStore([ 1152 `Unknown property ‘such-unknown-property’. Declaration dropped.`, 1153 ]); 1154 1155 const data = Symbol(); 1156 dispatch({ 1157 type: CSS_MESSAGE_ADD_MATCHING_ELEMENTS, 1158 id: getFirstMessage(getState()).id, 1159 elements: data, 1160 }); 1161 1162 const matchingElements = getAllCssMessagesMatchingElements(getState()); 1163 expect(matchingElements.size).toBe(1); 1164 expect(matchingElements.get(getFirstMessage(getState()).id)).toBe(data); 1165 1166 dispatch(actions.messagesClear()); 1167 1168 expect(getAllCssMessagesMatchingElements(getState()).size).toBe(0); 1169 }); 1170 1171 it("cleans the cssMessagesMatchingElements property when messages are pruned", () => { 1172 const { dispatch, getState } = setupStore([], { 1173 storeOptions: { 1174 logLimit: 2, 1175 }, 1176 }); 1177 1178 // Add 2 css warnings message and their associated data. 1179 dispatch( 1180 actions.messagesAdd([ 1181 stubPackets.get( 1182 `Unknown property ‘such-unknown-property’. Declaration dropped.` 1183 ), 1184 ]) 1185 ); 1186 dispatch( 1187 actions.messagesAdd([ 1188 stubPackets.get( 1189 `Error in parsing value for ‘padding-top’. Declaration dropped.` 1190 ), 1191 ]) 1192 ); 1193 1194 const messages = getMutableMessagesById(getState()); 1195 1196 const data1 = Symbol(); 1197 const data2 = Symbol(); 1198 const [id1, id2] = [...messages.keys()]; 1199 1200 dispatch({ 1201 type: CSS_MESSAGE_ADD_MATCHING_ELEMENTS, 1202 id: id1, 1203 elements: data1, 1204 }); 1205 dispatch({ 1206 type: CSS_MESSAGE_ADD_MATCHING_ELEMENTS, 1207 id: id2, 1208 elements: data2, 1209 }); 1210 1211 let matchingElements = getAllCssMessagesMatchingElements(getState()); 1212 expect(matchingElements.size).toBe(2); 1213 1214 // This addition will remove the first css warning. 1215 dispatch( 1216 actions.messagesAdd([stubPackets.get("console.log(undefined)")]) 1217 ); 1218 1219 matchingElements = getAllCssMessagesMatchingElements(getState()); 1220 expect(matchingElements.size).toBe(1); 1221 expect(matchingElements.get(id2)).toBe(data2); 1222 1223 // This addition will remove the second css warning. 1224 dispatch( 1225 actions.messagesAdd([stubPackets.get("console.log('foobar', 'test')")]) 1226 ); 1227 1228 expect(getAllCssMessagesMatchingElements(getState()).size).toBe(0); 1229 }); 1230 }); 1231 1232 describe("messagesAdd", () => { 1233 it("still log repeated message over logLimit, but only repeated ones", () => { 1234 // Log two distinct messages 1235 const key1 = "console.log('foobar', 'test')"; 1236 const key2 = "console.log(undefined)"; 1237 const { dispatch, getState } = setupStore([key1, key2], { 1238 storeOptions: { 1239 logLimit: 2, 1240 }, 1241 }); 1242 1243 // Then repeat the last one two times and log the first one again 1244 const packet1 = clonePacket(stubPackets.get(key2)); 1245 const packet2 = clonePacket(stubPackets.get(key2)); 1246 const packet3 = clonePacket(stubPackets.get(key1)); 1247 1248 // Repeat ID must be the same even if the timestamp is different. 1249 packet1.timeStamp = packet1.timeStamp + 1; 1250 packet2.timeStamp = packet2.timeStamp + 2; 1251 packet3.timeStamp = packet3.timeStamp + 3; 1252 dispatch(actions.messagesAdd([packet1, packet2, packet3])); 1253 1254 // There is still only two messages being logged, 1255 const messages = getMutableMessagesById(getState()); 1256 expect(messages.size).toBe(2); 1257 1258 // the second one being repeated 3 times 1259 const repeat = getAllRepeatById(getState()); 1260 expect(repeat[getFirstMessage(getState()).id]).toBe(3); 1261 expect(repeat[getLastMessage(getState()).id]).toBe(undefined); 1262 }); 1263 }); 1264 1265 describe("messageRemove", () => { 1266 it("removes the message from the store", () => { 1267 const { dispatch, getState } = setupStore([ 1268 "console.trace()", 1269 "console.log(undefined)", 1270 "console.trace()", 1271 "console.log(undefined)", 1272 ]); 1273 1274 let expanded = getAllMessagesUiById(getState()); 1275 expect(expanded.length).toBe(2); 1276 1277 const secondTraceMessage = getMessageAt(getState(), 2); 1278 dispatch(actions.messageRemove(secondTraceMessage.id)); 1279 1280 const messages = getMutableMessagesById(getState()); 1281 const { mutableMessagesOrder } = getState().messages; 1282 // The messages was removed 1283 expect(messages.size).toBe(3); 1284 expect(mutableMessagesOrder.length).toBe(3); 1285 1286 // Its id was removed from the messagesUI property as well 1287 expanded = getAllMessagesUiById(getState()); 1288 expect(expanded.length).toBe(1); 1289 expect(expanded.includes(secondTraceMessage.id)).toBeFalsy(); 1290 }); 1291 }); 1292 1293 describe("disabledMessagesById", () => { 1294 it("adds messages ids to disabledMessagesById when message disable action is called", () => { 1295 const { dispatch, getState } = setupStore(); 1296 1297 dispatch(actions.messagesDisable(["message1", "message2"])); 1298 1299 const disabledMessages = getAllDisabledMessagesById(getState()); 1300 expect(disabledMessages).toEqual(["message1", "message2"]); 1301 }); 1302 1303 it("clears disabledMessagesById in response to MESSAGES_CLEAR action", () => { 1304 const { dispatch, getState } = setupStore(); 1305 1306 dispatch(actions.messagesDisable(["message1", "message2"])); 1307 1308 let disabledMessages = getAllDisabledMessagesById(getState()); 1309 expect(disabledMessages).toEqual(["message1", "message2"]); 1310 1311 dispatch(actions.messagesClear()); 1312 1313 disabledMessages = getAllDisabledMessagesById(getState()); 1314 expect(disabledMessages).toEqual([]); 1315 }); 1316 1317 it("remove message id from disabledMessagesById when the message is removed", () => { 1318 const { dispatch, getState } = setupStore( 1319 [ 1320 "console.log('foobar', 'test')", 1321 "XHR GET request update", 1322 "console.log(undefined)", 1323 ], 1324 { 1325 actions, 1326 storeOptions: { 1327 logLimit: 3, 1328 }, 1329 } 1330 ); 1331 1332 // This is `console.log('foobar', 'test'` 1333 const firstMessageId = getMessageAt(getState(), 0).id; 1334 // This is for `XHR GET request update` 1335 const secondMessageId = getMessageAt(getState(), 1).id; 1336 1337 dispatch(actions.messagesDisable([firstMessageId, secondMessageId])); 1338 1339 let disabledMessages = getAllDisabledMessagesById(getState()); 1340 expect(disabledMessages).toEqual([firstMessageId, secondMessageId]); 1341 1342 // Adding a new message should prune the first(oldest) message and should 1343 // remove its id from the disabled messages list. 1344 const packet = stubPackets.get("GET request"); 1345 dispatch(actions.messagesAdd([packet])); 1346 1347 disabledMessages = getAllDisabledMessagesById(getState()); 1348 expect(disabledMessages).toEqual([secondMessageId]); 1349 }); 1350 }); 1351 });