1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @emails react-core
    
  8.  */
    
  9. 
    
  10. 'use strict';
    
  11. 
    
  12. describe('EventPluginRegistry', () => {
    
  13.   let EventPluginRegistry;
    
  14.   let createPlugin;
    
  15. 
    
  16.   beforeEach(() => {
    
  17.     jest.resetModules();
    
  18.     // These tests are intentionally testing the private injection interface.
    
  19.     // The public API surface of this is covered by other tests so
    
  20.     // if `EventPluginRegistry` is ever deleted, these tests should be
    
  21.     // safe to remove too.
    
  22.     EventPluginRegistry = require('react-native-renderer/src/legacy-events/EventPluginRegistry');
    
  23. 
    
  24.     createPlugin = function (properties) {
    
  25.       return Object.assign({extractEvents: function () {}}, properties);
    
  26.     };
    
  27.   });
    
  28. 
    
  29.   it('should be able to inject ordering before plugins', () => {
    
  30.     const OnePlugin = createPlugin();
    
  31.     const TwoPlugin = createPlugin();
    
  32.     const ThreePlugin = createPlugin();
    
  33. 
    
  34.     EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);
    
  35.     EventPluginRegistry.injectEventPluginsByName({
    
  36.       one: OnePlugin,
    
  37.       two: TwoPlugin,
    
  38.     });
    
  39.     EventPluginRegistry.injectEventPluginsByName({
    
  40.       three: ThreePlugin,
    
  41.     });
    
  42. 
    
  43.     expect(EventPluginRegistry.plugins.length).toBe(3);
    
  44.     expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);
    
  45.     expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);
    
  46.     expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);
    
  47.   });
    
  48. 
    
  49.   it('should be able to inject plugins before and after ordering', () => {
    
  50.     const OnePlugin = createPlugin();
    
  51.     const TwoPlugin = createPlugin();
    
  52.     const ThreePlugin = createPlugin();
    
  53. 
    
  54.     EventPluginRegistry.injectEventPluginsByName({
    
  55.       one: OnePlugin,
    
  56.       two: TwoPlugin,
    
  57.     });
    
  58.     EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);
    
  59.     EventPluginRegistry.injectEventPluginsByName({
    
  60.       three: ThreePlugin,
    
  61.     });
    
  62. 
    
  63.     expect(EventPluginRegistry.plugins.length).toBe(3);
    
  64.     expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);
    
  65.     expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);
    
  66.     expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);
    
  67.   });
    
  68. 
    
  69.   it('should be able to inject repeated plugins and out-of-order', () => {
    
  70.     const OnePlugin = createPlugin();
    
  71.     const TwoPlugin = createPlugin();
    
  72.     const ThreePlugin = createPlugin();
    
  73. 
    
  74.     EventPluginRegistry.injectEventPluginsByName({
    
  75.       one: OnePlugin,
    
  76.       three: ThreePlugin,
    
  77.     });
    
  78.     EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);
    
  79.     EventPluginRegistry.injectEventPluginsByName({
    
  80.       two: TwoPlugin,
    
  81.       three: ThreePlugin,
    
  82.     });
    
  83. 
    
  84.     expect(EventPluginRegistry.plugins.length).toBe(3);
    
  85.     expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);
    
  86.     expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);
    
  87.     expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);
    
  88.   });
    
  89. 
    
  90.   it('should throw if plugin does not implement `extractEvents`', () => {
    
  91.     const BadPlugin = {};
    
  92. 
    
  93.     EventPluginRegistry.injectEventPluginOrder(['bad']);
    
  94. 
    
  95.     expect(function () {
    
  96.       EventPluginRegistry.injectEventPluginsByName({
    
  97.         bad: BadPlugin,
    
  98.       });
    
  99.     }).toThrowError(
    
  100.       'EventPluginRegistry: Event plugins must implement an `extractEvents` ' +
    
  101.         'method, but `bad` does not.',
    
  102.     );
    
  103.   });
    
  104. 
    
  105.   it('should throw if plugin does not exist in ordering', () => {
    
  106.     const OnePlugin = createPlugin();
    
  107.     const RandomPlugin = createPlugin();
    
  108. 
    
  109.     EventPluginRegistry.injectEventPluginOrder(['one']);
    
  110. 
    
  111.     expect(function () {
    
  112.       EventPluginRegistry.injectEventPluginsByName({
    
  113.         one: OnePlugin,
    
  114.         random: RandomPlugin,
    
  115.       });
    
  116.     }).toThrowError(
    
  117.       'EventPluginRegistry: Cannot inject event plugins that do not exist ' +
    
  118.         'in the plugin ordering, `random`.',
    
  119.     );
    
  120.   });
    
  121. 
    
  122.   it('should throw if ordering is injected more than once', () => {
    
  123.     const pluginOrdering = [];
    
  124. 
    
  125.     EventPluginRegistry.injectEventPluginOrder(pluginOrdering);
    
  126. 
    
  127.     expect(function () {
    
  128.       EventPluginRegistry.injectEventPluginOrder(pluginOrdering);
    
  129.     }).toThrowError(
    
  130.       'EventPluginRegistry: Cannot inject event plugin ordering more than ' +
    
  131.         'once. You are likely trying to load more than one copy of React.',
    
  132.     );
    
  133.   });
    
  134. 
    
  135.   it('should throw if different plugins injected using same name', () => {
    
  136.     const OnePlugin = createPlugin();
    
  137.     const TwoPlugin = createPlugin();
    
  138. 
    
  139.     EventPluginRegistry.injectEventPluginsByName({same: OnePlugin});
    
  140. 
    
  141.     expect(function () {
    
  142.       EventPluginRegistry.injectEventPluginsByName({same: TwoPlugin});
    
  143.     }).toThrowError(
    
  144.       'EventPluginRegistry: Cannot inject two different event plugins using ' +
    
  145.         'the same name, `same`.',
    
  146.     );
    
  147.   });
    
  148. 
    
  149.   it('should publish registration names of injected plugins', () => {
    
  150.     const OnePlugin = createPlugin({
    
  151.       eventTypes: {
    
  152.         click: {registrationName: 'onClick'},
    
  153.         focus: {registrationName: 'onFocus'},
    
  154.       },
    
  155.     });
    
  156.     const TwoPlugin = createPlugin({
    
  157.       eventTypes: {
    
  158.         magic: {
    
  159.           phasedRegistrationNames: {
    
  160.             bubbled: 'onMagicBubble',
    
  161.             captured: 'onMagicCapture',
    
  162.           },
    
  163.         },
    
  164.       },
    
  165.     });
    
  166. 
    
  167.     EventPluginRegistry.injectEventPluginsByName({one: OnePlugin});
    
  168.     EventPluginRegistry.injectEventPluginOrder(['one', 'two']);
    
  169. 
    
  170.     expect(
    
  171.       Object.keys(EventPluginRegistry.registrationNameModules).length,
    
  172.     ).toBe(2);
    
  173.     expect(EventPluginRegistry.registrationNameModules.onClick).toBe(OnePlugin);
    
  174.     expect(EventPluginRegistry.registrationNameModules.onFocus).toBe(OnePlugin);
    
  175. 
    
  176.     EventPluginRegistry.injectEventPluginsByName({two: TwoPlugin});
    
  177. 
    
  178.     expect(
    
  179.       Object.keys(EventPluginRegistry.registrationNameModules).length,
    
  180.     ).toBe(4);
    
  181.     expect(EventPluginRegistry.registrationNameModules.onMagicBubble).toBe(
    
  182.       TwoPlugin,
    
  183.     );
    
  184.     expect(EventPluginRegistry.registrationNameModules.onMagicCapture).toBe(
    
  185.       TwoPlugin,
    
  186.     );
    
  187.   });
    
  188. 
    
  189.   it('should throw if multiple registration names collide', () => {
    
  190.     const OnePlugin = createPlugin({
    
  191.       eventTypes: {
    
  192.         photoCapture: {registrationName: 'onPhotoCapture'},
    
  193.       },
    
  194.     });
    
  195.     const TwoPlugin = createPlugin({
    
  196.       eventTypes: {
    
  197.         photo: {
    
  198.           phasedRegistrationNames: {
    
  199.             bubbled: 'onPhotoBubble',
    
  200.             captured: 'onPhotoCapture',
    
  201.           },
    
  202.         },
    
  203.       },
    
  204.     });
    
  205. 
    
  206.     EventPluginRegistry.injectEventPluginsByName({
    
  207.       one: OnePlugin,
    
  208.       two: TwoPlugin,
    
  209.     });
    
  210. 
    
  211.     expect(function () {
    
  212.       EventPluginRegistry.injectEventPluginOrder(['one', 'two']);
    
  213.     }).toThrowError(
    
  214.       'EventPluginRegistry: More than one plugin attempted to publish the same ' +
    
  215.         'registration name, `onPhotoCapture`.',
    
  216.     );
    
  217.   });
    
  218. 
    
  219.   it('should throw if an invalid event is published', () => {
    
  220.     const OnePlugin = createPlugin({
    
  221.       eventTypes: {
    
  222.         badEvent: {
    
  223.           /* missing configuration */
    
  224.         },
    
  225.       },
    
  226.     });
    
  227. 
    
  228.     EventPluginRegistry.injectEventPluginsByName({one: OnePlugin});
    
  229. 
    
  230.     expect(function () {
    
  231.       EventPluginRegistry.injectEventPluginOrder(['one']);
    
  232.     }).toThrowError(
    
  233.       'EventPluginRegistry: Failed to publish event `badEvent` for plugin ' +
    
  234.         '`one`.',
    
  235.     );
    
  236.   });
    
  237. });