DefaultReconnectionHandler.test.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import '../src/GlobalExports';
  2. import { UserSpecifiedDisplay } from '../src/Platform/Circuits/UserSpecifiedDisplay';
  3. import { DefaultReconnectionHandler } from '../src/Platform/Circuits/DefaultReconnectionHandler';
  4. import { NullLogger} from '../src/Platform/Logging/Loggers';
  5. import { resolveOptions, ReconnectionOptions } from "../src/Platform/Circuits/BlazorOptions";
  6. import { ReconnectDisplay } from '../src/Platform/Circuits/ReconnectDisplay';
  7. const defaultReconnectionOptions = resolveOptions().reconnectionOptions;
  8. describe('DefaultReconnectionHandler', () => {
  9. it('toggles user-specified UI on disconnection/connection', () => {
  10. const element = attachUserSpecifiedUI(defaultReconnectionOptions);
  11. const handler = new DefaultReconnectionHandler(NullLogger.instance);
  12. // Shows on disconnection
  13. handler.onConnectionDown(defaultReconnectionOptions);
  14. expect(element.className).toBe(UserSpecifiedDisplay.ShowClassName);
  15. // Hides on reconnection
  16. handler.onConnectionUp();
  17. expect(element.className).toBe(UserSpecifiedDisplay.HideClassName);
  18. document.body.removeChild(element);
  19. });
  20. it('hides display on connection up, and stops retrying', async () => {
  21. const testDisplay = createTestDisplay();
  22. const reconnect = jest.fn().mockResolvedValue(true);
  23. const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect);
  24. handler.onConnectionDown({
  25. maxRetries: 1000,
  26. retryIntervalMilliseconds: 100,
  27. dialogId: 'ignored'
  28. });
  29. handler.onConnectionUp();
  30. expect(testDisplay.hide).toHaveBeenCalled();
  31. await delay(200);
  32. expect(reconnect).not.toHaveBeenCalled();
  33. });
  34. it('shows display on connection down', async () => {
  35. const testDisplay = createTestDisplay();
  36. const reconnect = jest.fn().mockResolvedValue(true);
  37. const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect);
  38. handler.onConnectionDown({
  39. maxRetries: 1000,
  40. retryIntervalMilliseconds: 100,
  41. dialogId: 'ignored'
  42. });
  43. expect(testDisplay.show).toHaveBeenCalled();
  44. expect(testDisplay.failed).not.toHaveBeenCalled();
  45. expect(reconnect).not.toHaveBeenCalled();
  46. await delay(150);
  47. expect(reconnect).toHaveBeenCalledTimes(1);
  48. });
  49. // Skipped while under investigation: https://github.com/aspnet/AspNetCore/issues/12578
  50. // it('invokes failed if reconnect fails', async () => {
  51. // const testDisplay = createTestDisplay();
  52. // const reconnect = jest.fn().mockRejectedValue(null);
  53. // const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect);
  54. // window.console.error = jest.fn();
  55. // handler.onConnectionDown({
  56. // maxRetries: 3,
  57. // retryIntervalMilliseconds: 20,
  58. // dialogId: 'ignored'
  59. // });
  60. // await delay(500);
  61. // expect(testDisplay.show).toHaveBeenCalled();
  62. // expect(testDisplay.failed).toHaveBeenCalled();
  63. // expect(reconnect).toHaveBeenCalledTimes(3);
  64. // });
  65. });
  66. function attachUserSpecifiedUI(options: ReconnectionOptions): Element {
  67. const element = document.createElement('div');
  68. element.id = options.dialogId;
  69. element.className = UserSpecifiedDisplay.HideClassName;
  70. document.body.appendChild(element);
  71. return element;
  72. }
  73. function delay(durationMilliseconds: number) {
  74. return new Promise(resolve => setTimeout(resolve, durationMilliseconds));
  75. }
  76. function createTestDisplay(): ReconnectDisplay {
  77. return {
  78. show: jest.fn(),
  79. hide: jest.fn(),
  80. failed: jest.fn()
  81. };
  82. }