Best JavaScript code snippet using playwright-internal
TrackingSubscriptions-test.internal.js
Source:TrackingSubscriptions-test.internal.js  
1/**2 * Copyright (c) 2013-present, Facebook, Inc.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @jest-environment node8 */9'use strict';10describe('TrackingSubscriptions', () => {11  let SchedulerTracking;12  let ReactFeatureFlags;13  let currentTime;14  let onInteractionScheduledWorkCompleted;15  let onInteractionTracked;16  let onWorkCanceled;17  let onWorkScheduled;18  let onWorkStarted;19  let onWorkStopped;20  let throwInOnInteractionScheduledWorkCompleted;21  let throwInOnInteractionTracked;22  let throwInOnWorkCanceled;23  let throwInOnWorkScheduled;24  let throwInOnWorkStarted;25  let throwInOnWorkStopped;26  let firstSubscriber;27  let secondSubscriber;28  const firstEvent = {id: 0, name: 'first', timestamp: 0};29  const secondEvent = {id: 1, name: 'second', timestamp: 0};30  const threadID = 123;31  function loadModules({enableSchedulerTracking, autoSubscribe = true}) {32    jest.resetModules();33    jest.useFakeTimers();34    currentTime = 0;35    ReactFeatureFlags = require('shared/ReactFeatureFlags');36    ReactFeatureFlags.enableSchedulerTracking = enableSchedulerTracking;37    SchedulerTracking = require('schedule/tracking');38    throwInOnInteractionScheduledWorkCompleted = false;39    throwInOnInteractionTracked = false;40    throwInOnWorkCanceled = false;41    throwInOnWorkScheduled = false;42    throwInOnWorkStarted = false;43    throwInOnWorkStopped = false;44    onInteractionScheduledWorkCompleted = jest.fn(() => {45      if (throwInOnInteractionScheduledWorkCompleted) {46        throw Error('Expected error onInteractionScheduledWorkCompleted');47      }48    });49    onInteractionTracked = jest.fn(() => {50      if (throwInOnInteractionTracked) {51        throw Error('Expected error onInteractionTracked');52      }53    });54    onWorkCanceled = jest.fn(() => {55      if (throwInOnWorkCanceled) {56        throw Error('Expected error onWorkCanceled');57      }58    });59    onWorkScheduled = jest.fn(() => {60      if (throwInOnWorkScheduled) {61        throw Error('Expected error onWorkScheduled');62      }63    });64    onWorkStarted = jest.fn(() => {65      if (throwInOnWorkStarted) {66        throw Error('Expected error onWorkStarted');67      }68    });69    onWorkStopped = jest.fn(() => {70      if (throwInOnWorkStopped) {71        throw Error('Expected error onWorkStopped');72      }73    });74    firstSubscriber = {75      onInteractionScheduledWorkCompleted,76      onInteractionTracked,77      onWorkCanceled,78      onWorkScheduled,79      onWorkStarted,80      onWorkStopped,81    };82    secondSubscriber = {83      onInteractionScheduledWorkCompleted: jest.fn(),84      onInteractionTracked: jest.fn(),85      onWorkCanceled: jest.fn(),86      onWorkScheduled: jest.fn(),87      onWorkStarted: jest.fn(),88      onWorkStopped: jest.fn(),89    };90    if (autoSubscribe) {91      SchedulerTracking.unstable_subscribe(firstSubscriber);92      SchedulerTracking.unstable_subscribe(secondSubscriber);93    }94  }95  describe('enabled', () => {96    beforeEach(() => loadModules({enableSchedulerTracking: true}));97    it('should lazily subscribe to tracking and unsubscribe again if there are no external subscribers', () => {98      loadModules({enableSchedulerTracking: true, autoSubscribe: false});99      expect(SchedulerTracking.__subscriberRef.current).toBe(null);100      SchedulerTracking.unstable_subscribe(firstSubscriber);101      expect(SchedulerTracking.__subscriberRef.current).toBeDefined();102      SchedulerTracking.unstable_subscribe(secondSubscriber);103      expect(SchedulerTracking.__subscriberRef.current).toBeDefined();104      SchedulerTracking.unstable_unsubscribe(secondSubscriber);105      expect(SchedulerTracking.__subscriberRef.current).toBeDefined();106      SchedulerTracking.unstable_unsubscribe(firstSubscriber);107      expect(SchedulerTracking.__subscriberRef.current).toBe(null);108    });109    describe('error handling', () => {110      it('should cover onInteractionTracked/onWorkStarted within', done => {111        SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {112          const mock = jest.fn();113          // It should call the callback before re-throwing114          throwInOnInteractionTracked = true;115          expect(() =>116            SchedulerTracking.unstable_track(117              secondEvent.name,118              currentTime,119              mock,120              threadID,121            ),122          ).toThrow('Expected error onInteractionTracked');123          throwInOnInteractionTracked = false;124          expect(mock).toHaveBeenCalledTimes(1);125          throwInOnWorkStarted = true;126          expect(() =>127            SchedulerTracking.unstable_track(128              secondEvent.name,129              currentTime,130              mock,131              threadID,132            ),133          ).toThrow('Expected error onWorkStarted');134          expect(mock).toHaveBeenCalledTimes(2);135          // It should restore the previous/outer interactions136          expect(SchedulerTracking.unstable_getCurrent()).toMatchInteractions([137            firstEvent,138          ]);139          // It should call other subscribers despite the earlier error140          expect(secondSubscriber.onInteractionTracked).toHaveBeenCalledTimes(141            3,142          );143          expect(secondSubscriber.onWorkStarted).toHaveBeenCalledTimes(3);144          done();145        });146      });147      it('should cover onWorkStopped within track', done => {148        SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {149          let innerInteraction;150          const mock = jest.fn(() => {151            innerInteraction = Array.from(152              SchedulerTracking.unstable_getCurrent(),153            )[1];154          });155          throwInOnWorkStopped = true;156          expect(() =>157            SchedulerTracking.unstable_track(158              secondEvent.name,159              currentTime,160              mock,161            ),162          ).toThrow('Expected error onWorkStopped');163          throwInOnWorkStopped = false;164          // It should restore the previous/outer interactions165          expect(SchedulerTracking.unstable_getCurrent()).toMatchInteractions([166            firstEvent,167          ]);168          // It should update the interaction count so as not to interfere with subsequent calls169          expect(innerInteraction.__count).toBe(0);170          // It should call other subscribers despite the earlier error171          expect(secondSubscriber.onWorkStopped).toHaveBeenCalledTimes(1);172          done();173        });174      });175      it('should cover onInteractionScheduledWorkCompleted within track', done => {176        SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {177          const mock = jest.fn();178          throwInOnInteractionScheduledWorkCompleted = true;179          expect(() =>180            SchedulerTracking.unstable_track(181              secondEvent.name,182              currentTime,183              mock,184            ),185          ).toThrow('Expected error onInteractionScheduledWorkCompleted');186          throwInOnInteractionScheduledWorkCompleted = false;187          // It should restore the previous/outer interactions188          expect(SchedulerTracking.unstable_getCurrent()).toMatchInteractions([189            firstEvent,190          ]);191          // It should call other subscribers despite the earlier error192          expect(193            secondSubscriber.onInteractionScheduledWorkCompleted,194          ).toHaveBeenCalledTimes(1);195          done();196        });197      });198      it('should cover the callback within track', done => {199        expect(onWorkStarted).not.toHaveBeenCalled();200        expect(onWorkStopped).not.toHaveBeenCalled();201        expect(() => {202          SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {203            throw Error('Expected error callback');204          });205        }).toThrow('Expected error callback');206        expect(onWorkStarted).toHaveBeenCalledTimes(1);207        expect(onWorkStopped).toHaveBeenCalledTimes(1);208        done();209      });210      it('should cover onWorkScheduled within wrap', done => {211        SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {212          const interaction = Array.from(213            SchedulerTracking.unstable_getCurrent(),214          )[0];215          const beforeCount = interaction.__count;216          throwInOnWorkScheduled = true;217          expect(() => SchedulerTracking.unstable_wrap(() => {})).toThrow(218            'Expected error onWorkScheduled',219          );220          // It should not update the interaction count so as not to interfere with subsequent calls221          expect(interaction.__count).toBe(beforeCount);222          // It should call other subscribers despite the earlier error223          expect(secondSubscriber.onWorkScheduled).toHaveBeenCalledTimes(1);224          done();225        });226      });227      it('should cover onWorkStarted within wrap', () => {228        const mock = jest.fn();229        let interaction, wrapped;230        SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {231          interaction = Array.from(SchedulerTracking.unstable_getCurrent())[0];232          wrapped = SchedulerTracking.unstable_wrap(mock);233        });234        expect(interaction.__count).toBe(1);235        throwInOnWorkStarted = true;236        expect(wrapped).toThrow('Expected error onWorkStarted');237        // It should call the callback before re-throwing238        expect(mock).toHaveBeenCalledTimes(1);239        // It should update the interaction count so as not to interfere with subsequent calls240        expect(interaction.__count).toBe(0);241        // It should call other subscribers despite the earlier error242        expect(secondSubscriber.onWorkStarted).toHaveBeenCalledTimes(2);243      });244      it('should cover onWorkStopped within wrap', done => {245        SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {246          const outerInteraction = Array.from(247            SchedulerTracking.unstable_getCurrent(),248          )[0];249          expect(outerInteraction.__count).toBe(1);250          let wrapped;251          let innerInteraction;252          SchedulerTracking.unstable_track(253            secondEvent.name,254            currentTime,255            () => {256              innerInteraction = Array.from(257                SchedulerTracking.unstable_getCurrent(),258              )[1];259              expect(outerInteraction.__count).toBe(1);260              expect(innerInteraction.__count).toBe(1);261              wrapped = SchedulerTracking.unstable_wrap(jest.fn());262              expect(outerInteraction.__count).toBe(2);263              expect(innerInteraction.__count).toBe(2);264            },265          );266          expect(outerInteraction.__count).toBe(2);267          expect(innerInteraction.__count).toBe(1);268          throwInOnWorkStopped = true;269          expect(wrapped).toThrow('Expected error onWorkStopped');270          throwInOnWorkStopped = false;271          // It should restore the previous interactions272          expect(SchedulerTracking.unstable_getCurrent()).toMatchInteractions([273            outerInteraction,274          ]);275          // It should update the interaction count so as not to interfere with subsequent calls276          expect(outerInteraction.__count).toBe(1);277          expect(innerInteraction.__count).toBe(0);278          expect(secondSubscriber.onWorkStopped).toHaveBeenCalledTimes(2);279          done();280        });281      });282      it('should cover the callback within wrap', done => {283        expect(onWorkStarted).not.toHaveBeenCalled();284        expect(onWorkStopped).not.toHaveBeenCalled();285        let wrapped;286        let interaction;287        SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {288          interaction = Array.from(SchedulerTracking.unstable_getCurrent())[0];289          wrapped = SchedulerTracking.unstable_wrap(() => {290            throw Error('Expected error wrap');291          });292        });293        expect(onWorkStarted).toHaveBeenCalledTimes(1);294        expect(onWorkStopped).toHaveBeenCalledTimes(1);295        expect(wrapped).toThrow('Expected error wrap');296        expect(onWorkStarted).toHaveBeenCalledTimes(2);297        expect(onWorkStopped).toHaveBeenCalledTimes(2);298        expect(onWorkStopped).toHaveBeenLastNotifiedOfWork([interaction]);299        done();300      });301      it('should cover onWorkCanceled within wrap', () => {302        let interaction, wrapped;303        SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {304          interaction = Array.from(SchedulerTracking.unstable_getCurrent())[0];305          wrapped = SchedulerTracking.unstable_wrap(jest.fn());306        });307        expect(interaction.__count).toBe(1);308        throwInOnWorkCanceled = true;309        expect(wrapped.cancel).toThrow('Expected error onWorkCanceled');310        expect(onWorkCanceled).toHaveBeenCalledTimes(1);311        // It should update the interaction count so as not to interfere with subsequent calls312        expect(interaction.__count).toBe(0);313        expect(314          onInteractionScheduledWorkCompleted,315        ).toHaveBeenLastNotifiedOfInteraction(firstEvent);316        // It should call other subscribers despite the earlier error317        expect(secondSubscriber.onWorkCanceled).toHaveBeenCalledTimes(1);318      });319    });320    it('calls lifecycle methods for track', () => {321      expect(onInteractionTracked).not.toHaveBeenCalled();322      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();323      SchedulerTracking.unstable_track(324        firstEvent.name,325        currentTime,326        () => {327          expect(onInteractionTracked).toHaveBeenCalledTimes(1);328          expect(onInteractionTracked).toHaveBeenLastNotifiedOfInteraction(329            firstEvent,330          );331          expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();332          expect(onWorkStarted).toHaveBeenCalledTimes(1);333          expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(334            new Set([firstEvent]),335            threadID,336          );337          expect(onWorkStopped).not.toHaveBeenCalled();338          SchedulerTracking.unstable_track(339            secondEvent.name,340            currentTime,341            () => {342              expect(onInteractionTracked).toHaveBeenCalledTimes(2);343              expect(onInteractionTracked).toHaveBeenLastNotifiedOfInteraction(344                secondEvent,345              );346              expect(347                onInteractionScheduledWorkCompleted,348              ).not.toHaveBeenCalled();349              expect(onWorkStarted).toHaveBeenCalledTimes(2);350              expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(351                new Set([firstEvent, secondEvent]),352                threadID,353              );354              expect(onWorkStopped).not.toHaveBeenCalled();355            },356            threadID,357          );358          expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);359          expect(360            onInteractionScheduledWorkCompleted,361          ).toHaveBeenLastNotifiedOfInteraction(secondEvent);362          expect(onWorkStopped).toHaveBeenCalledTimes(1);363          expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(364            new Set([firstEvent, secondEvent]),365            threadID,366          );367        },368        threadID,369      );370      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);371      expect(372        onInteractionScheduledWorkCompleted,373      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);374      expect(onWorkScheduled).not.toHaveBeenCalled();375      expect(onWorkCanceled).not.toHaveBeenCalled();376      expect(onWorkStarted).toHaveBeenCalledTimes(2);377      expect(onWorkStopped).toHaveBeenCalledTimes(2);378      expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(379        new Set([firstEvent]),380        threadID,381      );382    });383    it('calls lifecycle methods for wrap', () => {384      const unwrapped = jest.fn();385      let wrapped;386      SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {387        expect(onInteractionTracked).toHaveBeenCalledTimes(1);388        expect(onInteractionTracked).toHaveBeenLastNotifiedOfInteraction(389          firstEvent,390        );391        SchedulerTracking.unstable_track(secondEvent.name, currentTime, () => {392          expect(onInteractionTracked).toHaveBeenCalledTimes(2);393          expect(onInteractionTracked).toHaveBeenLastNotifiedOfInteraction(394            secondEvent,395          );396          wrapped = SchedulerTracking.unstable_wrap(unwrapped, threadID);397          expect(onWorkScheduled).toHaveBeenCalledTimes(1);398          expect(onWorkScheduled).toHaveBeenLastNotifiedOfWork(399            new Set([firstEvent, secondEvent]),400            threadID,401          );402        });403      });404      expect(onInteractionTracked).toHaveBeenCalledTimes(2);405      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();406      wrapped();407      expect(unwrapped).toHaveBeenCalled();408      expect(onWorkScheduled).toHaveBeenCalledTimes(1);409      expect(onWorkCanceled).not.toHaveBeenCalled();410      expect(onWorkStarted).toHaveBeenCalledTimes(3);411      expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(412        new Set([firstEvent, secondEvent]),413        threadID,414      );415      expect(onWorkStopped).toHaveBeenCalledTimes(3);416      expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(417        new Set([firstEvent, secondEvent]),418        threadID,419      );420      expect(421        onInteractionScheduledWorkCompleted.mock.calls[0][0],422      ).toMatchInteraction(firstEvent);423      expect(424        onInteractionScheduledWorkCompleted.mock.calls[1][0],425      ).toMatchInteraction(secondEvent);426    });427    it('should call the correct interaction subscriber methods when a wrapped callback is canceled', () => {428      const fnOne = jest.fn();429      const fnTwo = jest.fn();430      let wrappedOne, wrappedTwo;431      SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {432        wrappedOne = SchedulerTracking.unstable_wrap(fnOne, threadID);433        SchedulerTracking.unstable_track(secondEvent.name, currentTime, () => {434          wrappedTwo = SchedulerTracking.unstable_wrap(fnTwo, threadID);435        });436      });437      expect(onInteractionTracked).toHaveBeenCalledTimes(2);438      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();439      expect(onWorkCanceled).not.toHaveBeenCalled();440      expect(onWorkStarted).toHaveBeenCalledTimes(2);441      expect(onWorkStopped).toHaveBeenCalledTimes(2);442      wrappedTwo.cancel();443      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);444      expect(445        onInteractionScheduledWorkCompleted,446      ).toHaveBeenLastNotifiedOfInteraction(secondEvent);447      expect(onWorkCanceled).toHaveBeenCalledTimes(1);448      expect(onWorkCanceled).toHaveBeenLastNotifiedOfWork(449        new Set([firstEvent, secondEvent]),450        threadID,451      );452      wrappedOne.cancel();453      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);454      expect(455        onInteractionScheduledWorkCompleted,456      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);457      expect(onWorkCanceled).toHaveBeenCalledTimes(2);458      expect(onWorkCanceled).toHaveBeenLastNotifiedOfWork(459        new Set([firstEvent]),460        threadID,461      );462      expect(fnOne).not.toHaveBeenCalled();463      expect(fnTwo).not.toHaveBeenCalled();464    });465    it('should not end an interaction twice if wrap is used to schedule follow up work within another wrap', () => {466      const fnOne = jest.fn(() => {467        wrappedTwo = SchedulerTracking.unstable_wrap(fnTwo, threadID);468      });469      const fnTwo = jest.fn();470      let wrappedOne, wrappedTwo;471      SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {472        wrappedOne = SchedulerTracking.unstable_wrap(fnOne, threadID);473      });474      expect(onInteractionTracked).toHaveBeenCalledTimes(1);475      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();476      wrappedOne();477      expect(onInteractionTracked).toHaveBeenCalledTimes(1);478      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();479      wrappedTwo();480      expect(onInteractionTracked).toHaveBeenCalledTimes(1);481      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);482      expect(483        onInteractionScheduledWorkCompleted,484      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);485    });486    it('should not decrement the interaction count twice if a wrapped function is run twice', () => {487      const unwrappedOne = jest.fn();488      const unwrappedTwo = jest.fn();489      let wrappedOne, wrappedTwo;490      SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {491        wrappedOne = SchedulerTracking.unstable_wrap(unwrappedOne, threadID);492        wrappedTwo = SchedulerTracking.unstable_wrap(unwrappedTwo, threadID);493      });494      expect(onInteractionTracked).toHaveBeenCalledTimes(1);495      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();496      wrappedOne();497      expect(unwrappedOne).toHaveBeenCalledTimes(1);498      expect(onInteractionTracked).toHaveBeenCalledTimes(1);499      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();500      wrappedOne();501      expect(unwrappedOne).toHaveBeenCalledTimes(2);502      expect(onInteractionTracked).toHaveBeenCalledTimes(1);503      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();504      wrappedTwo();505      expect(onInteractionTracked).toHaveBeenCalledTimes(1);506      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);507      expect(508        onInteractionScheduledWorkCompleted,509      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);510    });511    it('should unsubscribe', () => {512      SchedulerTracking.unstable_unsubscribe(firstSubscriber);513      SchedulerTracking.unstable_track(firstEvent.name, currentTime, () => {});514      expect(onInteractionTracked).not.toHaveBeenCalled();515    });516  });517  describe('disabled', () => {518    beforeEach(() => loadModules({enableSchedulerTracking: false}));519    // TODO520  });...TracingSubscriptions-test.internal.js
Source:TracingSubscriptions-test.internal.js  
1/**2 * Copyright (c) Facebook, Inc. and its affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @jest-environment node8 */9'use strict';10describe('TracingSubscriptions', () => {11  let SchedulerTracing;12  let ReactFeatureFlags;13  let currentTime;14  let onInteractionScheduledWorkCompleted;15  let onInteractionTraced;16  let onWorkCanceled;17  let onWorkScheduled;18  let onWorkStarted;19  let onWorkStopped;20  let throwInOnInteractionScheduledWorkCompleted;21  let throwInOnInteractionTraced;22  let throwInOnWorkCanceled;23  let throwInOnWorkScheduled;24  let throwInOnWorkStarted;25  let throwInOnWorkStopped;26  let firstSubscriber;27  let secondSubscriber;28  const firstEvent = {id: 0, name: 'first', timestamp: 0};29  const secondEvent = {id: 1, name: 'second', timestamp: 0};30  const threadID = 123;31  function loadModules({enableSchedulerTracing, autoSubscribe = true}) {32    jest.resetModules();33    jest.useFakeTimers();34    currentTime = 0;35    ReactFeatureFlags = require('shared/ReactFeatureFlags');36    ReactFeatureFlags.enableSchedulerTracing = enableSchedulerTracing;37    SchedulerTracing = require('scheduler/tracing');38    throwInOnInteractionScheduledWorkCompleted = false;39    throwInOnInteractionTraced = false;40    throwInOnWorkCanceled = false;41    throwInOnWorkScheduled = false;42    throwInOnWorkStarted = false;43    throwInOnWorkStopped = false;44    onInteractionScheduledWorkCompleted = jest.fn(() => {45      if (throwInOnInteractionScheduledWorkCompleted) {46        throw Error('Expected error onInteractionScheduledWorkCompleted');47      }48    });49    onInteractionTraced = jest.fn(() => {50      if (throwInOnInteractionTraced) {51        throw Error('Expected error onInteractionTraced');52      }53    });54    onWorkCanceled = jest.fn(() => {55      if (throwInOnWorkCanceled) {56        throw Error('Expected error onWorkCanceled');57      }58    });59    onWorkScheduled = jest.fn(() => {60      if (throwInOnWorkScheduled) {61        throw Error('Expected error onWorkScheduled');62      }63    });64    onWorkStarted = jest.fn(() => {65      if (throwInOnWorkStarted) {66        throw Error('Expected error onWorkStarted');67      }68    });69    onWorkStopped = jest.fn(() => {70      if (throwInOnWorkStopped) {71        throw Error('Expected error onWorkStopped');72      }73    });74    firstSubscriber = {75      onInteractionScheduledWorkCompleted,76      onInteractionTraced,77      onWorkCanceled,78      onWorkScheduled,79      onWorkStarted,80      onWorkStopped,81    };82    secondSubscriber = {83      onInteractionScheduledWorkCompleted: jest.fn(),84      onInteractionTraced: jest.fn(),85      onWorkCanceled: jest.fn(),86      onWorkScheduled: jest.fn(),87      onWorkStarted: jest.fn(),88      onWorkStopped: jest.fn(),89    };90    if (autoSubscribe) {91      SchedulerTracing.unstable_subscribe(firstSubscriber);92      SchedulerTracing.unstable_subscribe(secondSubscriber);93    }94  }95  describe('enabled', () => {96    beforeEach(() => loadModules({enableSchedulerTracing: true}));97    it('should lazily subscribe to tracing and unsubscribe again if there are no external subscribers', () => {98      loadModules({enableSchedulerTracing: true, autoSubscribe: false});99      expect(SchedulerTracing.__subscriberRef.current).toBe(null);100      SchedulerTracing.unstable_subscribe(firstSubscriber);101      expect(SchedulerTracing.__subscriberRef.current).toBeDefined();102      SchedulerTracing.unstable_subscribe(secondSubscriber);103      expect(SchedulerTracing.__subscriberRef.current).toBeDefined();104      SchedulerTracing.unstable_unsubscribe(secondSubscriber);105      expect(SchedulerTracing.__subscriberRef.current).toBeDefined();106      SchedulerTracing.unstable_unsubscribe(firstSubscriber);107      expect(SchedulerTracing.__subscriberRef.current).toBe(null);108    });109    describe('error handling', () => {110      it('should cover onInteractionTraced/onWorkStarted within', done => {111        SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {112          const mock = jest.fn();113          // It should call the callback before re-throwing114          throwInOnInteractionTraced = true;115          expect(() =>116            SchedulerTracing.unstable_trace(117              secondEvent.name,118              currentTime,119              mock,120              threadID,121            ),122          ).toThrow('Expected error onInteractionTraced');123          throwInOnInteractionTraced = false;124          expect(mock).toHaveBeenCalledTimes(1);125          throwInOnWorkStarted = true;126          expect(() =>127            SchedulerTracing.unstable_trace(128              secondEvent.name,129              currentTime,130              mock,131              threadID,132            ),133          ).toThrow('Expected error onWorkStarted');134          expect(mock).toHaveBeenCalledTimes(2);135          // It should restore the previous/outer interactions136          expect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions([137            firstEvent,138          ]);139          // It should call other subscribers despite the earlier error140          expect(secondSubscriber.onInteractionTraced).toHaveBeenCalledTimes(3);141          expect(secondSubscriber.onWorkStarted).toHaveBeenCalledTimes(3);142          done();143        });144      });145      it('should cover onWorkStopped within trace', done => {146        SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {147          let innerInteraction;148          const mock = jest.fn(() => {149            innerInteraction = Array.from(150              SchedulerTracing.unstable_getCurrent(),151            )[1];152          });153          throwInOnWorkStopped = true;154          expect(() =>155            SchedulerTracing.unstable_trace(156              secondEvent.name,157              currentTime,158              mock,159            ),160          ).toThrow('Expected error onWorkStopped');161          throwInOnWorkStopped = false;162          // It should restore the previous/outer interactions163          expect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions([164            firstEvent,165          ]);166          // It should update the interaction count so as not to interfere with subsequent calls167          expect(innerInteraction.__count).toBe(0);168          // It should call other subscribers despite the earlier error169          expect(secondSubscriber.onWorkStopped).toHaveBeenCalledTimes(1);170          done();171        });172      });173      it('should cover onInteractionScheduledWorkCompleted within trace', done => {174        SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {175          const mock = jest.fn();176          throwInOnInteractionScheduledWorkCompleted = true;177          expect(() =>178            SchedulerTracing.unstable_trace(179              secondEvent.name,180              currentTime,181              mock,182            ),183          ).toThrow('Expected error onInteractionScheduledWorkCompleted');184          throwInOnInteractionScheduledWorkCompleted = false;185          // It should restore the previous/outer interactions186          expect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions([187            firstEvent,188          ]);189          // It should call other subscribers despite the earlier error190          expect(191            secondSubscriber.onInteractionScheduledWorkCompleted,192          ).toHaveBeenCalledTimes(1);193          done();194        });195      });196      it('should cover the callback within trace', done => {197        expect(onWorkStarted).not.toHaveBeenCalled();198        expect(onWorkStopped).not.toHaveBeenCalled();199        expect(() => {200          SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {201            throw Error('Expected error callback');202          });203        }).toThrow('Expected error callback');204        expect(onWorkStarted).toHaveBeenCalledTimes(1);205        expect(onWorkStopped).toHaveBeenCalledTimes(1);206        done();207      });208      it('should cover onWorkScheduled within wrap', done => {209        SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {210          const interaction = Array.from(211            SchedulerTracing.unstable_getCurrent(),212          )[0];213          const beforeCount = interaction.__count;214          throwInOnWorkScheduled = true;215          expect(() => SchedulerTracing.unstable_wrap(() => {})).toThrow(216            'Expected error onWorkScheduled',217          );218          // It should not update the interaction count so as not to interfere with subsequent calls219          expect(interaction.__count).toBe(beforeCount);220          // It should call other subscribers despite the earlier error221          expect(secondSubscriber.onWorkScheduled).toHaveBeenCalledTimes(1);222          done();223        });224      });225      it('should cover onWorkStarted within wrap', () => {226        const mock = jest.fn();227        let interaction, wrapped;228        SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {229          interaction = Array.from(SchedulerTracing.unstable_getCurrent())[0];230          wrapped = SchedulerTracing.unstable_wrap(mock);231        });232        expect(interaction.__count).toBe(1);233        throwInOnWorkStarted = true;234        expect(wrapped).toThrow('Expected error onWorkStarted');235        // It should call the callback before re-throwing236        expect(mock).toHaveBeenCalledTimes(1);237        // It should update the interaction count so as not to interfere with subsequent calls238        expect(interaction.__count).toBe(0);239        // It should call other subscribers despite the earlier error240        expect(secondSubscriber.onWorkStarted).toHaveBeenCalledTimes(2);241      });242      it('should cover onWorkStopped within wrap', done => {243        SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {244          const outerInteraction = Array.from(245            SchedulerTracing.unstable_getCurrent(),246          )[0];247          expect(outerInteraction.__count).toBe(1);248          let wrapped;249          let innerInteraction;250          SchedulerTracing.unstable_trace(secondEvent.name, currentTime, () => {251            innerInteraction = Array.from(252              SchedulerTracing.unstable_getCurrent(),253            )[1];254            expect(outerInteraction.__count).toBe(1);255            expect(innerInteraction.__count).toBe(1);256            wrapped = SchedulerTracing.unstable_wrap(jest.fn());257            expect(outerInteraction.__count).toBe(2);258            expect(innerInteraction.__count).toBe(2);259          });260          expect(outerInteraction.__count).toBe(2);261          expect(innerInteraction.__count).toBe(1);262          throwInOnWorkStopped = true;263          expect(wrapped).toThrow('Expected error onWorkStopped');264          throwInOnWorkStopped = false;265          // It should restore the previous interactions266          expect(SchedulerTracing.unstable_getCurrent()).toMatchInteractions([267            outerInteraction,268          ]);269          // It should update the interaction count so as not to interfere with subsequent calls270          expect(outerInteraction.__count).toBe(1);271          expect(innerInteraction.__count).toBe(0);272          expect(secondSubscriber.onWorkStopped).toHaveBeenCalledTimes(2);273          done();274        });275      });276      it('should cover the callback within wrap', done => {277        expect(onWorkStarted).not.toHaveBeenCalled();278        expect(onWorkStopped).not.toHaveBeenCalled();279        let wrapped;280        let interaction;281        SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {282          interaction = Array.from(SchedulerTracing.unstable_getCurrent())[0];283          wrapped = SchedulerTracing.unstable_wrap(() => {284            throw Error('Expected error wrap');285          });286        });287        expect(onWorkStarted).toHaveBeenCalledTimes(1);288        expect(onWorkStopped).toHaveBeenCalledTimes(1);289        expect(wrapped).toThrow('Expected error wrap');290        expect(onWorkStarted).toHaveBeenCalledTimes(2);291        expect(onWorkStopped).toHaveBeenCalledTimes(2);292        expect(onWorkStopped).toHaveBeenLastNotifiedOfWork([interaction]);293        done();294      });295      it('should cover onWorkCanceled within wrap', () => {296        let interaction, wrapped;297        SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {298          interaction = Array.from(SchedulerTracing.unstable_getCurrent())[0];299          wrapped = SchedulerTracing.unstable_wrap(jest.fn());300        });301        expect(interaction.__count).toBe(1);302        throwInOnWorkCanceled = true;303        expect(wrapped.cancel).toThrow('Expected error onWorkCanceled');304        expect(onWorkCanceled).toHaveBeenCalledTimes(1);305        // It should update the interaction count so as not to interfere with subsequent calls306        expect(interaction.__count).toBe(0);307        expect(308          onInteractionScheduledWorkCompleted,309        ).toHaveBeenLastNotifiedOfInteraction(firstEvent);310        // It should call other subscribers despite the earlier error311        expect(secondSubscriber.onWorkCanceled).toHaveBeenCalledTimes(1);312      });313    });314    it('calls lifecycle methods for trace', () => {315      expect(onInteractionTraced).not.toHaveBeenCalled();316      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();317      SchedulerTracing.unstable_trace(318        firstEvent.name,319        currentTime,320        () => {321          expect(onInteractionTraced).toHaveBeenCalledTimes(1);322          expect(onInteractionTraced).toHaveBeenLastNotifiedOfInteraction(323            firstEvent,324          );325          expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();326          expect(onWorkStarted).toHaveBeenCalledTimes(1);327          expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(328            new Set([firstEvent]),329            threadID,330          );331          expect(onWorkStopped).not.toHaveBeenCalled();332          SchedulerTracing.unstable_trace(333            secondEvent.name,334            currentTime,335            () => {336              expect(onInteractionTraced).toHaveBeenCalledTimes(2);337              expect(onInteractionTraced).toHaveBeenLastNotifiedOfInteraction(338                secondEvent,339              );340              expect(341                onInteractionScheduledWorkCompleted,342              ).not.toHaveBeenCalled();343              expect(onWorkStarted).toHaveBeenCalledTimes(2);344              expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(345                new Set([firstEvent, secondEvent]),346                threadID,347              );348              expect(onWorkStopped).not.toHaveBeenCalled();349            },350            threadID,351          );352          expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);353          expect(354            onInteractionScheduledWorkCompleted,355          ).toHaveBeenLastNotifiedOfInteraction(secondEvent);356          expect(onWorkStopped).toHaveBeenCalledTimes(1);357          expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(358            new Set([firstEvent, secondEvent]),359            threadID,360          );361        },362        threadID,363      );364      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);365      expect(366        onInteractionScheduledWorkCompleted,367      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);368      expect(onWorkScheduled).not.toHaveBeenCalled();369      expect(onWorkCanceled).not.toHaveBeenCalled();370      expect(onWorkStarted).toHaveBeenCalledTimes(2);371      expect(onWorkStopped).toHaveBeenCalledTimes(2);372      expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(373        new Set([firstEvent]),374        threadID,375      );376    });377    it('calls lifecycle methods for wrap', () => {378      const unwrapped = jest.fn();379      let wrapped;380      SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {381        expect(onInteractionTraced).toHaveBeenCalledTimes(1);382        expect(onInteractionTraced).toHaveBeenLastNotifiedOfInteraction(383          firstEvent,384        );385        SchedulerTracing.unstable_trace(secondEvent.name, currentTime, () => {386          expect(onInteractionTraced).toHaveBeenCalledTimes(2);387          expect(onInteractionTraced).toHaveBeenLastNotifiedOfInteraction(388            secondEvent,389          );390          wrapped = SchedulerTracing.unstable_wrap(unwrapped, threadID);391          expect(onWorkScheduled).toHaveBeenCalledTimes(1);392          expect(onWorkScheduled).toHaveBeenLastNotifiedOfWork(393            new Set([firstEvent, secondEvent]),394            threadID,395          );396        });397      });398      expect(onInteractionTraced).toHaveBeenCalledTimes(2);399      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();400      wrapped();401      expect(unwrapped).toHaveBeenCalled();402      expect(onWorkScheduled).toHaveBeenCalledTimes(1);403      expect(onWorkCanceled).not.toHaveBeenCalled();404      expect(onWorkStarted).toHaveBeenCalledTimes(3);405      expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(406        new Set([firstEvent, secondEvent]),407        threadID,408      );409      expect(onWorkStopped).toHaveBeenCalledTimes(3);410      expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(411        new Set([firstEvent, secondEvent]),412        threadID,413      );414      expect(415        onInteractionScheduledWorkCompleted.mock.calls[0][0],416      ).toMatchInteraction(firstEvent);417      expect(418        onInteractionScheduledWorkCompleted.mock.calls[1][0],419      ).toMatchInteraction(secondEvent);420    });421    it('should call the correct interaction subscriber methods when a wrapped callback is canceled', () => {422      const fnOne = jest.fn();423      const fnTwo = jest.fn();424      let wrappedOne, wrappedTwo;425      SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {426        wrappedOne = SchedulerTracing.unstable_wrap(fnOne, threadID);427        SchedulerTracing.unstable_trace(secondEvent.name, currentTime, () => {428          wrappedTwo = SchedulerTracing.unstable_wrap(fnTwo, threadID);429        });430      });431      expect(onInteractionTraced).toHaveBeenCalledTimes(2);432      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();433      expect(onWorkCanceled).not.toHaveBeenCalled();434      expect(onWorkStarted).toHaveBeenCalledTimes(2);435      expect(onWorkStopped).toHaveBeenCalledTimes(2);436      wrappedTwo.cancel();437      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);438      expect(439        onInteractionScheduledWorkCompleted,440      ).toHaveBeenLastNotifiedOfInteraction(secondEvent);441      expect(onWorkCanceled).toHaveBeenCalledTimes(1);442      expect(onWorkCanceled).toHaveBeenLastNotifiedOfWork(443        new Set([firstEvent, secondEvent]),444        threadID,445      );446      wrappedOne.cancel();447      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);448      expect(449        onInteractionScheduledWorkCompleted,450      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);451      expect(onWorkCanceled).toHaveBeenCalledTimes(2);452      expect(onWorkCanceled).toHaveBeenLastNotifiedOfWork(453        new Set([firstEvent]),454        threadID,455      );456      expect(fnOne).not.toHaveBeenCalled();457      expect(fnTwo).not.toHaveBeenCalled();458    });459    it('should not end an interaction twice if wrap is used to schedule follow up work within another wrap', () => {460      const fnOne = jest.fn(() => {461        wrappedTwo = SchedulerTracing.unstable_wrap(fnTwo, threadID);462      });463      const fnTwo = jest.fn();464      let wrappedOne, wrappedTwo;465      SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {466        wrappedOne = SchedulerTracing.unstable_wrap(fnOne, threadID);467      });468      expect(onInteractionTraced).toHaveBeenCalledTimes(1);469      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();470      wrappedOne();471      expect(onInteractionTraced).toHaveBeenCalledTimes(1);472      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();473      wrappedTwo();474      expect(onInteractionTraced).toHaveBeenCalledTimes(1);475      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);476      expect(477        onInteractionScheduledWorkCompleted,478      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);479    });480    it('should not decrement the interaction count twice if a wrapped function is run twice', () => {481      const unwrappedOne = jest.fn();482      const unwrappedTwo = jest.fn();483      let wrappedOne, wrappedTwo;484      SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {485        wrappedOne = SchedulerTracing.unstable_wrap(unwrappedOne, threadID);486        wrappedTwo = SchedulerTracing.unstable_wrap(unwrappedTwo, threadID);487      });488      expect(onInteractionTraced).toHaveBeenCalledTimes(1);489      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();490      wrappedOne();491      expect(unwrappedOne).toHaveBeenCalledTimes(1);492      expect(onInteractionTraced).toHaveBeenCalledTimes(1);493      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();494      wrappedOne();495      expect(unwrappedOne).toHaveBeenCalledTimes(2);496      expect(onInteractionTraced).toHaveBeenCalledTimes(1);497      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();498      wrappedTwo();499      expect(onInteractionTraced).toHaveBeenCalledTimes(1);500      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);501      expect(502        onInteractionScheduledWorkCompleted,503      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);504    });505    it('should unsubscribe', () => {506      SchedulerTracing.unstable_unsubscribe(firstSubscriber);507      SchedulerTracing.unstable_trace(firstEvent.name, currentTime, () => {});508      expect(onInteractionTraced).not.toHaveBeenCalled();509    });510  });511  describe('disabled', () => {512    beforeEach(() => loadModules({enableSchedulerTracing: false}));513    // TODO514  });...InteractionTrackingSubscriptions-test.internal.js
Source:InteractionTrackingSubscriptions-test.internal.js  
1/**2 * Copyright (c) 2013-present, Facebook, Inc.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @jest-environment node8 */9'use strict';10describe('InteractionTracking', () => {11  let InteractionTracking;12  let InteractionTrackingSubscriptions;13  let ReactFeatureFlags;14  let currentTime;15  let onInteractionScheduledWorkCompleted;16  let onInteractionTracked;17  let onWorkCanceled;18  let onWorkScheduled;19  let onWorkStarted;20  let onWorkStopped;21  let throwInOnInteractionScheduledWorkCompleted;22  let throwInOnInteractionTracked;23  let throwInOnWorkCanceled;24  let throwInOnWorkScheduled;25  let throwInOnWorkStarted;26  let throwInOnWorkStopped;27  let firstSubscriber;28  let secondSubscriber;29  const firstEvent = {id: 0, name: 'first', timestamp: 0};30  const secondEvent = {id: 1, name: 'second', timestamp: 0};31  const threadID = 123;32  function loadModules({enableInteractionTracking}) {33    jest.resetModules();34    jest.useFakeTimers();35    currentTime = 0;36    ReactFeatureFlags = require('shared/ReactFeatureFlags');37    ReactFeatureFlags.enableInteractionTracking = enableInteractionTracking;38    InteractionTracking = require('interaction-tracking');39    InteractionTrackingSubscriptions = require('interaction-tracking/subscriptions');40    throwInOnInteractionScheduledWorkCompleted = false;41    throwInOnInteractionTracked = false;42    throwInOnWorkCanceled = false;43    throwInOnWorkScheduled = false;44    throwInOnWorkStarted = false;45    throwInOnWorkStopped = false;46    onInteractionScheduledWorkCompleted = jest.fn(() => {47      if (throwInOnInteractionScheduledWorkCompleted) {48        throw Error('Expected error onInteractionScheduledWorkCompleted');49      }50    });51    onInteractionTracked = jest.fn(() => {52      if (throwInOnInteractionTracked) {53        throw Error('Expected error onInteractionTracked');54      }55    });56    onWorkCanceled = jest.fn(() => {57      if (throwInOnWorkCanceled) {58        throw Error('Expected error onWorkCanceled');59      }60    });61    onWorkScheduled = jest.fn(() => {62      if (throwInOnWorkScheduled) {63        throw Error('Expected error onWorkScheduled');64      }65    });66    onWorkStarted = jest.fn(() => {67      if (throwInOnWorkStarted) {68        throw Error('Expected error onWorkStarted');69      }70    });71    onWorkStopped = jest.fn(() => {72      if (throwInOnWorkStopped) {73        throw Error('Expected error onWorkStopped');74      }75    });76    firstSubscriber = {77      onInteractionScheduledWorkCompleted,78      onInteractionTracked,79      onWorkCanceled,80      onWorkScheduled,81      onWorkStarted,82      onWorkStopped,83    };84    secondSubscriber = {85      onInteractionScheduledWorkCompleted: jest.fn(),86      onInteractionTracked: jest.fn(),87      onWorkCanceled: jest.fn(),88      onWorkScheduled: jest.fn(),89      onWorkStarted: jest.fn(),90      onWorkStopped: jest.fn(),91    };92    InteractionTrackingSubscriptions.subscribe(firstSubscriber);93    InteractionTrackingSubscriptions.subscribe(secondSubscriber);94  }95  describe('enabled', () => {96    beforeEach(() => loadModules({enableInteractionTracking: true}));97    describe('error handling', () => {98      it('should cover onInteractionTracked/onWorkStarted within', done => {99        InteractionTracking.track(firstEvent.name, currentTime, () => {100          const mock = jest.fn();101          // It should call the callback before re-throwing102          throwInOnInteractionTracked = true;103          expect(() =>104            InteractionTracking.track(105              secondEvent.name,106              currentTime,107              mock,108              threadID,109            ),110          ).toThrow('Expected error onInteractionTracked');111          throwInOnInteractionTracked = false;112          expect(mock).toHaveBeenCalledTimes(1);113          throwInOnWorkStarted = true;114          expect(() =>115            InteractionTracking.track(116              secondEvent.name,117              currentTime,118              mock,119              threadID,120            ),121          ).toThrow('Expected error onWorkStarted');122          expect(mock).toHaveBeenCalledTimes(2);123          // It should restore the previous/outer interactions124          expect(InteractionTracking.getCurrent()).toMatchInteractions([125            firstEvent,126          ]);127          // It should call other subscribers despite the earlier error128          expect(secondSubscriber.onInteractionTracked).toHaveBeenCalledTimes(129            3,130          );131          expect(secondSubscriber.onWorkStarted).toHaveBeenCalledTimes(3);132          done();133        });134      });135      it('should cover onWorkStopped within track', done => {136        InteractionTracking.track(firstEvent.name, currentTime, () => {137          let innerInteraction;138          const mock = jest.fn(() => {139            innerInteraction = Array.from(InteractionTracking.getCurrent())[1];140          });141          throwInOnWorkStopped = true;142          expect(() =>143            InteractionTracking.track(secondEvent.name, currentTime, mock),144          ).toThrow('Expected error onWorkStopped');145          throwInOnWorkStopped = false;146          // It should restore the previous/outer interactions147          expect(InteractionTracking.getCurrent()).toMatchInteractions([148            firstEvent,149          ]);150          // It should update the interaction count so as not to interfere with subsequent calls151          expect(innerInteraction.__count).toBe(0);152          // It should call other subscribers despite the earlier error153          expect(secondSubscriber.onWorkStopped).toHaveBeenCalledTimes(1);154          done();155        });156      });157      it('should cover onInteractionScheduledWorkCompleted within track', done => {158        InteractionTracking.track(firstEvent.name, currentTime, () => {159          const mock = jest.fn();160          throwInOnInteractionScheduledWorkCompleted = true;161          expect(() =>162            InteractionTracking.track(secondEvent.name, currentTime, mock),163          ).toThrow('Expected error onInteractionScheduledWorkCompleted');164          throwInOnInteractionScheduledWorkCompleted = false;165          // It should restore the previous/outer interactions166          expect(InteractionTracking.getCurrent()).toMatchInteractions([167            firstEvent,168          ]);169          // It should call other subscribers despite the earlier error170          expect(171            secondSubscriber.onInteractionScheduledWorkCompleted,172          ).toHaveBeenCalledTimes(1);173          done();174        });175      });176      it('should cover the callback within track', done => {177        expect(onWorkStarted).not.toHaveBeenCalled();178        expect(onWorkStopped).not.toHaveBeenCalled();179        expect(() => {180          InteractionTracking.track(firstEvent.name, currentTime, () => {181            throw Error('Expected error callback');182          });183        }).toThrow('Expected error callback');184        expect(onWorkStarted).toHaveBeenCalledTimes(1);185        expect(onWorkStopped).toHaveBeenCalledTimes(1);186        done();187      });188      it('should cover onWorkScheduled within wrap', done => {189        InteractionTracking.track(firstEvent.name, currentTime, () => {190          const interaction = Array.from(InteractionTracking.getCurrent())[0];191          const beforeCount = interaction.__count;192          throwInOnWorkScheduled = true;193          expect(() => InteractionTracking.wrap(() => {})).toThrow(194            'Expected error onWorkScheduled',195          );196          // It should not update the interaction count so as not to interfere with subsequent calls197          expect(interaction.__count).toBe(beforeCount);198          // It should call other subscribers despite the earlier error199          expect(secondSubscriber.onWorkScheduled).toHaveBeenCalledTimes(1);200          done();201        });202      });203      it('should cover onWorkStarted within wrap', () => {204        const mock = jest.fn();205        let interaction, wrapped;206        InteractionTracking.track(firstEvent.name, currentTime, () => {207          interaction = Array.from(InteractionTracking.getCurrent())[0];208          wrapped = InteractionTracking.wrap(mock);209        });210        expect(interaction.__count).toBe(1);211        throwInOnWorkStarted = true;212        expect(wrapped).toThrow('Expected error onWorkStarted');213        // It should call the callback before re-throwing214        expect(mock).toHaveBeenCalledTimes(1);215        // It should update the interaction count so as not to interfere with subsequent calls216        expect(interaction.__count).toBe(0);217        // It should call other subscribers despite the earlier error218        expect(secondSubscriber.onWorkStarted).toHaveBeenCalledTimes(2);219      });220      it('should cover onWorkStopped within wrap', done => {221        InteractionTracking.track(firstEvent.name, currentTime, () => {222          const outerInteraction = Array.from(223            InteractionTracking.getCurrent(),224          )[0];225          expect(outerInteraction.__count).toBe(1);226          let wrapped;227          let innerInteraction;228          InteractionTracking.track(secondEvent.name, currentTime, () => {229            innerInteraction = Array.from(InteractionTracking.getCurrent())[1];230            expect(outerInteraction.__count).toBe(1);231            expect(innerInteraction.__count).toBe(1);232            wrapped = InteractionTracking.wrap(jest.fn());233            expect(outerInteraction.__count).toBe(2);234            expect(innerInteraction.__count).toBe(2);235          });236          expect(outerInteraction.__count).toBe(2);237          expect(innerInteraction.__count).toBe(1);238          throwInOnWorkStopped = true;239          expect(wrapped).toThrow('Expected error onWorkStopped');240          throwInOnWorkStopped = false;241          // It should restore the previous interactions242          expect(InteractionTracking.getCurrent()).toMatchInteractions([243            outerInteraction,244          ]);245          // It should update the interaction count so as not to interfere with subsequent calls246          expect(outerInteraction.__count).toBe(1);247          expect(innerInteraction.__count).toBe(0);248          expect(secondSubscriber.onWorkStopped).toHaveBeenCalledTimes(2);249          done();250        });251      });252      it('should cover the callback within wrap', done => {253        expect(onWorkStarted).not.toHaveBeenCalled();254        expect(onWorkStopped).not.toHaveBeenCalled();255        let wrapped;256        let interaction;257        InteractionTracking.track(firstEvent.name, currentTime, () => {258          interaction = Array.from(InteractionTracking.getCurrent())[0];259          wrapped = InteractionTracking.wrap(() => {260            throw Error('Expected error wrap');261          });262        });263        expect(onWorkStarted).toHaveBeenCalledTimes(1);264        expect(onWorkStopped).toHaveBeenCalledTimes(1);265        expect(wrapped).toThrow('Expected error wrap');266        expect(onWorkStarted).toHaveBeenCalledTimes(2);267        expect(onWorkStopped).toHaveBeenCalledTimes(2);268        expect(onWorkStopped).toHaveBeenLastNotifiedOfWork([interaction]);269        done();270      });271      it('should cover onWorkCanceled within wrap', () => {272        let interaction, wrapped;273        InteractionTracking.track(firstEvent.name, currentTime, () => {274          interaction = Array.from(InteractionTracking.getCurrent())[0];275          wrapped = InteractionTracking.wrap(jest.fn());276        });277        expect(interaction.__count).toBe(1);278        throwInOnWorkCanceled = true;279        expect(wrapped.cancel).toThrow('Expected error onWorkCanceled');280        expect(onWorkCanceled).toHaveBeenCalledTimes(1);281        // It should update the interaction count so as not to interfere with subsequent calls282        expect(interaction.__count).toBe(0);283        expect(284          onInteractionScheduledWorkCompleted,285        ).toHaveBeenLastNotifiedOfInteraction(firstEvent);286        // It should call other subscribers despite the earlier error287        expect(secondSubscriber.onWorkCanceled).toHaveBeenCalledTimes(1);288      });289    });290    it('calls lifecycle methods for track', () => {291      expect(onInteractionTracked).not.toHaveBeenCalled();292      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();293      InteractionTracking.track(294        firstEvent.name,295        currentTime,296        () => {297          expect(onInteractionTracked).toHaveBeenCalledTimes(1);298          expect(onInteractionTracked).toHaveBeenLastNotifiedOfInteraction(299            firstEvent,300          );301          expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();302          expect(onWorkStarted).toHaveBeenCalledTimes(1);303          expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(304            new Set([firstEvent]),305            threadID,306          );307          expect(onWorkStopped).not.toHaveBeenCalled();308          InteractionTracking.track(309            secondEvent.name,310            currentTime,311            () => {312              expect(onInteractionTracked).toHaveBeenCalledTimes(2);313              expect(onInteractionTracked).toHaveBeenLastNotifiedOfInteraction(314                secondEvent,315              );316              expect(317                onInteractionScheduledWorkCompleted,318              ).not.toHaveBeenCalled();319              expect(onWorkStarted).toHaveBeenCalledTimes(2);320              expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(321                new Set([firstEvent, secondEvent]),322                threadID,323              );324              expect(onWorkStopped).not.toHaveBeenCalled();325            },326            threadID,327          );328          expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);329          expect(330            onInteractionScheduledWorkCompleted,331          ).toHaveBeenLastNotifiedOfInteraction(secondEvent);332          expect(onWorkStopped).toHaveBeenCalledTimes(1);333          expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(334            new Set([firstEvent, secondEvent]),335            threadID,336          );337        },338        threadID,339      );340      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);341      expect(342        onInteractionScheduledWorkCompleted,343      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);344      expect(onWorkScheduled).not.toHaveBeenCalled();345      expect(onWorkCanceled).not.toHaveBeenCalled();346      expect(onWorkStarted).toHaveBeenCalledTimes(2);347      expect(onWorkStopped).toHaveBeenCalledTimes(2);348      expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(349        new Set([firstEvent]),350        threadID,351      );352    });353    it('calls lifecycle methods for wrap', () => {354      const unwrapped = jest.fn();355      let wrapped;356      InteractionTracking.track(firstEvent.name, currentTime, () => {357        expect(onInteractionTracked).toHaveBeenCalledTimes(1);358        expect(onInteractionTracked).toHaveBeenLastNotifiedOfInteraction(359          firstEvent,360        );361        InteractionTracking.track(secondEvent.name, currentTime, () => {362          expect(onInteractionTracked).toHaveBeenCalledTimes(2);363          expect(onInteractionTracked).toHaveBeenLastNotifiedOfInteraction(364            secondEvent,365          );366          wrapped = InteractionTracking.wrap(unwrapped, threadID);367          expect(onWorkScheduled).toHaveBeenCalledTimes(1);368          expect(onWorkScheduled).toHaveBeenLastNotifiedOfWork(369            new Set([firstEvent, secondEvent]),370            threadID,371          );372        });373      });374      expect(onInteractionTracked).toHaveBeenCalledTimes(2);375      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();376      wrapped();377      expect(unwrapped).toHaveBeenCalled();378      expect(onWorkScheduled).toHaveBeenCalledTimes(1);379      expect(onWorkCanceled).not.toHaveBeenCalled();380      expect(onWorkStarted).toHaveBeenCalledTimes(3);381      expect(onWorkStarted).toHaveBeenLastNotifiedOfWork(382        new Set([firstEvent, secondEvent]),383        threadID,384      );385      expect(onWorkStopped).toHaveBeenCalledTimes(3);386      expect(onWorkStopped).toHaveBeenLastNotifiedOfWork(387        new Set([firstEvent, secondEvent]),388        threadID,389      );390      expect(391        onInteractionScheduledWorkCompleted.mock.calls[0][0],392      ).toMatchInteraction(firstEvent);393      expect(394        onInteractionScheduledWorkCompleted.mock.calls[1][0],395      ).toMatchInteraction(secondEvent);396    });397    it('should call the correct interaction subscriber methods when a wrapped callback is canceled', () => {398      const fnOne = jest.fn();399      const fnTwo = jest.fn();400      let wrappedOne, wrappedTwo;401      InteractionTracking.track(firstEvent.name, currentTime, () => {402        wrappedOne = InteractionTracking.wrap(fnOne, threadID);403        InteractionTracking.track(secondEvent.name, currentTime, () => {404          wrappedTwo = InteractionTracking.wrap(fnTwo, threadID);405        });406      });407      expect(onInteractionTracked).toHaveBeenCalledTimes(2);408      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();409      expect(onWorkCanceled).not.toHaveBeenCalled();410      expect(onWorkStarted).toHaveBeenCalledTimes(2);411      expect(onWorkStopped).toHaveBeenCalledTimes(2);412      wrappedTwo.cancel();413      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);414      expect(415        onInteractionScheduledWorkCompleted,416      ).toHaveBeenLastNotifiedOfInteraction(secondEvent);417      expect(onWorkCanceled).toHaveBeenCalledTimes(1);418      expect(onWorkCanceled).toHaveBeenLastNotifiedOfWork(419        new Set([firstEvent, secondEvent]),420        threadID,421      );422      wrappedOne.cancel();423      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(2);424      expect(425        onInteractionScheduledWorkCompleted,426      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);427      expect(onWorkCanceled).toHaveBeenCalledTimes(2);428      expect(onWorkCanceled).toHaveBeenLastNotifiedOfWork(429        new Set([firstEvent]),430        threadID,431      );432      expect(fnOne).not.toHaveBeenCalled();433      expect(fnTwo).not.toHaveBeenCalled();434    });435    it('should not end an interaction twice if wrap is used to schedule follow up work within another wrap', () => {436      const fnOne = jest.fn(() => {437        wrappedTwo = InteractionTracking.wrap(fnTwo, threadID);438      });439      const fnTwo = jest.fn();440      let wrappedOne, wrappedTwo;441      InteractionTracking.track(firstEvent.name, currentTime, () => {442        wrappedOne = InteractionTracking.wrap(fnOne, threadID);443      });444      expect(onInteractionTracked).toHaveBeenCalledTimes(1);445      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();446      wrappedOne();447      expect(onInteractionTracked).toHaveBeenCalledTimes(1);448      expect(onInteractionScheduledWorkCompleted).not.toHaveBeenCalled();449      wrappedTwo();450      expect(onInteractionTracked).toHaveBeenCalledTimes(1);451      expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1);452      expect(453        onInteractionScheduledWorkCompleted,454      ).toHaveBeenLastNotifiedOfInteraction(firstEvent);455    });456    it('should unsubscribe', () => {457      InteractionTrackingSubscriptions.unsubscribe(firstSubscriber);458      InteractionTracking.track(firstEvent.name, currentTime, () => {});459      expect(onInteractionTracked).not.toHaveBeenCalled();460    });461  });462  describe('disabled', () => {463    beforeEach(() => loadModules({enableInteractionTracking: false}));464    // TODO465  });...LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!
