Best JavaScript code snippet using playwright-internal
fluid-scroller.spec.js
Source:fluid-scroller.spec.js  
...137            (scrollableViewport.subject[axis.size] - thresholds.maxSpeedAt),138            scrollableViewport.subject.center[axis.crossAxisLine],139          );140          it('should not scroll if not past the start threshold', () => {141            autoScroller.onStateChange(state.idle, dragTo({142              selection: onStartBoundary,143              viewport: scrollableViewport,144            }));145            requestAnimationFrame.flush();146            expect(mocks.scrollWindow).not.toHaveBeenCalled();147          });148          it('should scroll if moving beyond the start threshold', () => {149            const target: Position = add(onStartBoundary, patch(axis.line, 1));150            autoScroller.onStateChange(state.idle, dragTo({151              selection: target,152              viewport: scrollableViewport,153            }));154            expect(mocks.scrollWindow).not.toHaveBeenCalled();155            // only called after a frame156            requestAnimationFrame.step();157            expect(mocks.scrollWindow).toHaveBeenCalled();158            // moving forwards159            const request: Position = mocks.scrollWindow.mock.calls[0][0];160            expect(request[axis.line]).toBeGreaterThan(0);161          });162          it('should throttle multiple scrolls into a single animation frame', () => {163            const target1: Position = add(onStartBoundary, patch(axis.line, 1));164            const target2: Position = add(onStartBoundary, patch(axis.line, 2));165            autoScroller.onStateChange(state.idle, dragTo({166              selection: target1,167              viewport: scrollableViewport,168            }));169            autoScroller.onStateChange(170              dragTo({171                selection: target1,172                viewport: scrollableViewport,173              }),174              dragTo({175                selection: target2,176                viewport: scrollableViewport,177              })178            );179            expect(mocks.scrollWindow).not.toHaveBeenCalled();180            // only called after a frame181            requestAnimationFrame.step();182            expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);183            // verification184            requestAnimationFrame.flush();185            expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);186            // not testing value called as we are not exposing getRequired scroll187          });188          it('should get faster the closer to the max speed point', () => {189            const target1: Position = add(onStartBoundary, patch(axis.line, 1));190            const target2: Position = add(onStartBoundary, patch(axis.line, 2));191            autoScroller.onStateChange(state.idle, dragTo({192              selection: target1,193              viewport: scrollableViewport,194            }));195            requestAnimationFrame.step();196            expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);197            const scroll1: Position = (mocks.scrollWindow.mock.calls[0][0] : any);198            autoScroller.onStateChange(199              dragTo({200                selection: target1,201                viewport: scrollableViewport,202              }),203              dragTo({204                selection: target2,205                viewport: scrollableViewport,206              })207            );208            requestAnimationFrame.step();209            expect(mocks.scrollWindow).toHaveBeenCalledTimes(2);210            const scroll2: Position = (mocks.scrollWindow.mock.calls[1][0] : any);211            expect(scroll1[axis.line]).toBeLessThan(scroll2[axis.line]);212            // validation213            expect(scroll1[axis.crossAxisLine]).toBe(0);214            expect(scroll2[axis.crossAxisLine]).toBe(0);215          });216          it('should have the top speed at the max speed point', () => {217            const expected: Position = patch(axis.line, config.maxScrollSpeed);218            autoScroller.onStateChange(state.idle, dragTo({219              selection: onMaxBoundary,220              viewport: scrollableViewport,221            }));222            requestAnimationFrame.step();223            expect(mocks.scrollWindow).toHaveBeenCalledWith(expected);224          });225          it('should have the top speed when moving beyond the max speed point', () => {226            const target: Position = add(onMaxBoundary, patch(axis.line, 1));227            const expected: Position = patch(axis.line, config.maxScrollSpeed);228            autoScroller.onStateChange(state.idle, dragTo({229              selection: target,230              viewport: scrollableViewport,231            }));232            requestAnimationFrame.step();233            expect(mocks.scrollWindow).toHaveBeenCalledWith(expected);234          });235          it('should not scroll if the item is too big', () => {236            const expanded: Area = getArea(237              expandByPosition(scrollableViewport.subject, { x: 1, y: 1 })238            );239            const tooBig: DraggableDimension = getDraggableDimension({240              descriptor: {241                id: 'too big',242                droppableId: preset.home.descriptor.id,243                // after the last item244                index: preset.inHomeList.length,245              },246              paddingBox: expanded,247            });248            const selection: Position = onMaxBoundary;249            const custom: State = (() => {250              const base: State = state.dragging(251                preset.inHome1.descriptor.id,252                selection,253              );254              const updated: State = {255                ...base,256                drag: {257                  ...base.drag,258                  initial: {259                    // $ExpectError260                    ...base.drag.initial,261                    descriptor: tooBig.descriptor,262                  },263                },264              };265              return addDraggable(updated, tooBig);266            })();267            autoScroller.onStateChange(state.idle, custom);268            requestAnimationFrame.flush();269            expect(mocks.scrollWindow).not.toHaveBeenCalled();270          });271          it('should not scroll if the window cannot scroll', () => {272            const target: Position = onMaxBoundary;273            autoScroller.onStateChange(state.idle, dragTo({274              selection: target,275              viewport: unscrollableViewport,276            }));277            requestAnimationFrame.step();278            expect(mocks.scrollWindow).not.toHaveBeenCalled();279          });280        });281        describe('moving backwards towards the start of window', () => {282          const windowScroll: Position = patch(axis.line, 10);283          const scrolledViewport: Viewport = scrollViewport(scrollableViewport, windowScroll);284          const onStartBoundary: Position = patch(285            axis.line,286            // at the boundary is not enough to start287            windowScroll[axis.line] + thresholds.startFrom,288            scrolledViewport.subject.center[axis.crossAxisLine],289          );290          const onMaxBoundary: Position = patch(291            axis.line,292            (windowScroll[axis.line] + thresholds.maxSpeedAt),293            scrolledViewport.subject.center[axis.crossAxisLine],294          );295          it('should not scroll if not past the start threshold', () => {296            autoScroller.onStateChange(297              state.idle,298              dragTo({299                selection: onStartBoundary,300                viewport: scrolledViewport,301              }),302            );303            requestAnimationFrame.flush();304            expect(mocks.scrollWindow).not.toHaveBeenCalled();305          });306          it('should scroll if moving beyond the start threshold', () => {307            const target: Position = subtract(onStartBoundary, patch(axis.line, 1));308            autoScroller.onStateChange(state.idle, dragTo({309              selection: target,310              viewport: scrolledViewport,311            }));312            expect(mocks.scrollWindow).not.toHaveBeenCalled();313            // only called after a frame314            requestAnimationFrame.step();315            expect(mocks.scrollWindow).toHaveBeenCalled();316            // moving backwards317            const request: Position = mocks.scrollWindow.mock.calls[0][0];318            expect(request[axis.line]).toBeLessThan(0);319          });320          it('should throttle multiple scrolls into a single animation frame', () => {321            const target1: Position = subtract(onStartBoundary, patch(axis.line, 1));322            const target2: Position = subtract(onStartBoundary, patch(axis.line, 2));323            autoScroller.onStateChange(state.idle, dragTo({324              selection: target1,325              viewport: scrolledViewport,326            }));327            autoScroller.onStateChange(328              dragTo({329                selection: target1,330                viewport: scrolledViewport,331              }),332              dragTo({333                selection: target2,334                viewport: scrolledViewport,335              }),336            );337            expect(mocks.scrollWindow).not.toHaveBeenCalled();338            // only called after a frame339            requestAnimationFrame.step();340            expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);341            // verification342            requestAnimationFrame.flush();343            expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);344            // not testing value called as we are not exposing getRequired scroll345          });346          it('should get faster the closer to the max speed point', () => {347            const target1: Position = subtract(onStartBoundary, patch(axis.line, 1));348            const target2: Position = subtract(onStartBoundary, patch(axis.line, 2));349            autoScroller.onStateChange(350              state.idle,351              dragTo({352                selection: target1,353                viewport: scrolledViewport,354              })355            );356            requestAnimationFrame.step();357            expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);358            const scroll1: Position = (mocks.scrollWindow.mock.calls[0][0] : any);359            autoScroller.onStateChange(360              dragTo({361                selection: target1,362                viewport: scrolledViewport,363              }),364              dragTo({365                selection: target2,366                viewport: scrolledViewport,367              }),368            );369            requestAnimationFrame.step();370            expect(mocks.scrollWindow).toHaveBeenCalledTimes(2);371            const scroll2: Position = (mocks.scrollWindow.mock.calls[1][0] : any);372            // moving backwards so a smaller value is bigger373            expect(scroll1[axis.line]).toBeGreaterThan(scroll2[axis.line]);374            // or put another way:375            expect(Math.abs(scroll1[axis.line])).toBeLessThan(Math.abs(scroll2[axis.line]));376            // validation377            expect(scroll1[axis.crossAxisLine]).toBe(0);378            expect(scroll2[axis.crossAxisLine]).toBe(0);379          });380          it('should have the top speed at the max speed point', () => {381            const target: Position = onMaxBoundary;382            const expected: Position = patch(axis.line, -config.maxScrollSpeed);383            autoScroller.onStateChange(state.idle, dragTo({384              selection: target,385              viewport: scrolledViewport,386            }));387            requestAnimationFrame.step();388            expect(mocks.scrollWindow).toHaveBeenCalledWith(expected);389          });390          it('should have the top speed when moving beyond the max speed point', () => {391            const target: Position = subtract(onMaxBoundary, patch(axis.line, 1));392            const expected: Position = patch(axis.line, -config.maxScrollSpeed);393            autoScroller.onStateChange(state.idle, dragTo({394              selection: target,395              viewport: scrolledViewport,396            }));397            requestAnimationFrame.step();398            expect(mocks.scrollWindow).toHaveBeenCalledWith(expected);399          });400          it('should not scroll if the item is too big', () => {401            const expanded: Area = getArea(402              expandByPosition(scrollableViewport.subject, { x: 1, y: 1 })403            );404            const tooBig: DraggableDimension = getDraggableDimension({405              descriptor: {406                id: 'too big',407                droppableId: preset.home.descriptor.id,408                // after the last item409                index: preset.inHomeList.length,410              },411              paddingBox: expanded,412            });413            const selection: Position = onMaxBoundary;414            const custom: State = (() => {415              const base: State = state.dragging(416                preset.inHome1.descriptor.id,417                selection,418              );419              const updated: State = {420                ...base,421                drag: {422                  ...base.drag,423                  initial: {424                    // $ExpectError425                    ...base.drag.initial,426                    descriptor: tooBig.descriptor,427                  },428                },429              };430              return addDraggable(updated, tooBig);431            })();432            autoScroller.onStateChange(state.idle, custom);433            requestAnimationFrame.flush();434            expect(mocks.scrollWindow).not.toHaveBeenCalled();435          });436          it('should not scroll if the window cannot scroll', () => {437            const target: Position = onMaxBoundary;438            autoScroller.onStateChange(state.idle, dragTo({439              selection: target,440              viewport: unscrollableViewport,441            }));442            requestAnimationFrame.step();443            expect(mocks.scrollWindow).not.toHaveBeenCalled();444          });445        });446        // just some light tests to ensure that cross axis moving also works447        describe('moving forward on the cross axis', () => {448          const onStartBoundary: Position = patch(449            axis.line,450            scrollableViewport.subject.center[axis.line],451            // to the boundary is not enough to start452            (scrollableViewport.subject[axis.crossAxisSize] - crossAxisThresholds.startFrom),453          );454          it('should not scroll if not past the start threshold', () => {455            autoScroller.onStateChange(state.idle, dragTo({456              selection: onStartBoundary,457              viewport: scrollableViewport,458            }));459            requestAnimationFrame.flush();460            expect(mocks.scrollWindow).not.toHaveBeenCalled();461          });462          it('should scroll if moving beyond the start threshold', () => {463            const target: Position = add(onStartBoundary, patch(axis.crossAxisLine, 1));464            autoScroller.onStateChange(state.idle, dragTo({465              selection: target,466              viewport: scrollableViewport,467            }));468            expect(mocks.scrollWindow).not.toHaveBeenCalled();469            // only called after a frame470            requestAnimationFrame.step();471            expect(mocks.scrollWindow).toHaveBeenCalled();472            // moving forwards473            const request: Position = mocks.scrollWindow.mock.calls[0][0];474            expect(request[axis.crossAxisLine]).toBeGreaterThan(0);475          });476        });477        // just some light tests to ensure that cross axis moving also works478        describe('moving backward on the cross axis', () => {479          const windowScroll: Position = patch(axis.crossAxisLine, 10);480          const scrolled: Viewport = scrollViewport(scrollableViewport, windowScroll);481          const onStartBoundary: Position = patch(482            axis.line,483            scrolled.subject.center[axis.line],484            // to the boundary is not enough to start485            windowScroll[axis.crossAxisLine] + (crossAxisThresholds.startFrom)486          );487          it('should not scroll if not past the start threshold', () => {488            autoScroller.onStateChange(state.idle, dragTo({489              selection: onStartBoundary,490              viewport: scrolled,491            }));492            requestAnimationFrame.flush();493            expect(mocks.scrollWindow).not.toHaveBeenCalled();494          });495          it('should scroll if moving beyond the start threshold', () => {496            const target: Position = subtract(onStartBoundary, patch(axis.crossAxisLine, 1));497            autoScroller.onStateChange(state.idle, dragTo({498              selection: target,499              viewport: scrolled,500            }));501            expect(mocks.scrollWindow).not.toHaveBeenCalled();502            // only called after a frame503            requestAnimationFrame.step();504            expect(mocks.scrollWindow).toHaveBeenCalled();505            // moving backwards506            const request: Position = mocks.scrollWindow.mock.calls[0][0];507            expect(request[axis.crossAxisLine]).toBeLessThan(0);508          });509        });510        describe('big draggable', () => {511          const onMaxBoundaryOfBoth: Position = patch(512            axis.line,513            (scrollableViewport.subject[axis.size] - thresholds.maxSpeedAt),514            (scrollableViewport.subject[axis.crossAxisSize] - crossAxisThresholds.maxSpeedAt),515          );516          describe('bigger on the main axis', () => {517            it('should not allow scrolling on the main axis, but allow scrolling on the cross axis', () => {518              const expanded: Area = getArea(519                expandByPosition(scrollableViewport.subject, patch(axis.line, 1))520              );521              const tooBigOnMainAxis: DraggableDimension = getDraggableDimension({522                descriptor: {523                  id: 'too big',524                  droppableId: preset.home.descriptor.id,525                  // after the last item526                  index: preset.inHomeList.length,527                },528                paddingBox: expanded,529              });530              const selection: Position = onMaxBoundaryOfBoth;531              const custom: State = (() => {532                const base: State = state.dragging(533                  preset.inHome1.descriptor.id,534                  selection,535                  scrollableViewport,536                );537                const updated: State = {538                  ...base,539                  drag: {540                    ...base.drag,541                    initial: {542                      // $ExpectError543                      ...base.drag.initial,544                      descriptor: tooBigOnMainAxis.descriptor,545                    },546                  },547                };548                return addDraggable(updated, tooBigOnMainAxis);549              })();550              autoScroller.onStateChange(state.idle, custom);551              requestAnimationFrame.step();552              expect(mocks.scrollWindow).toHaveBeenCalledWith(553                // scroll ocurred on the cross axis, but not on the main axis554                patch(axis.crossAxisLine, config.maxScrollSpeed)555              );556            });557          });558          describe('bigger on the cross axis', () => {559            it('should not allow scrolling on the cross axis, but allow scrolling on the main axis', () => {560              const expanded: Area = getArea(561                expandByPosition(scrollableViewport.subject, patch(axis.crossAxisLine, 1))562              );563              const tooBigOnCrossAxis: DraggableDimension = getDraggableDimension({564                descriptor: {565                  id: 'too big',566                  droppableId: preset.home.descriptor.id,567                  // after the last item568                  index: preset.inHomeList.length,569                },570                paddingBox: expanded,571              });572              const selection: Position = onMaxBoundaryOfBoth;573              const custom: State = (() => {574                const base: State = state.dragging(575                  preset.inHome1.descriptor.id,576                  selection,577                  scrollableViewport,578                );579                const updated: State = {580                  ...base,581                  drag: {582                    ...base.drag,583                    initial: {584                      // $ExpectError585                      ...base.drag.initial,586                      descriptor: tooBigOnCrossAxis.descriptor,587                    },588                  },589                };590                return addDraggable(updated, tooBigOnCrossAxis);591              })();592              autoScroller.onStateChange(state.idle, custom);593              requestAnimationFrame.step();594              expect(mocks.scrollWindow).toHaveBeenCalledWith(595                // scroll ocurred on the main axis, but not on the cross axis596                patch(axis.line, config.maxScrollSpeed)597              );598            });599          });600          describe('bigger on both axis', () => {601            it('should not allow scrolling on any axis', () => {602              const expanded: Area = getArea(603                expandByPosition(scrollableViewport.subject, patch(axis.line, 1, 1))604              );605              const tooBig: DraggableDimension = getDraggableDimension({606                descriptor: {607                  id: 'too big',608                  droppableId: preset.home.descriptor.id,609                  // after the last item610                  index: preset.inHomeList.length,611                },612                paddingBox: expanded,613              });614              const selection: Position = onMaxBoundaryOfBoth;615              const custom: State = (() => {616                const base: State = state.dragging(617                  preset.inHome1.descriptor.id,618                  selection,619                  scrollableViewport,620                );621                const updated: State = {622                  ...base,623                  drag: {624                    ...base.drag,625                    initial: {626                      // $ExpectError627                      ...base.drag.initial,628                      descriptor: tooBig.descriptor,629                    },630                  },631                };632                return addDraggable(updated, tooBig);633              })();634              autoScroller.onStateChange(state.idle, custom);635              requestAnimationFrame.step();636              expect(mocks.scrollWindow).not.toHaveBeenCalled();637            });638          });639        });640      });641      describe('droppable scrolling', () => {642        const thresholds: PixelThresholds = getPixelThresholds(frame, axis);643        const crossAxisThresholds: PixelThresholds = getPixelThresholds(644          frame,645          axis === vertical ? horizontal : vertical646        );647        const maxScrollSpeed: Position = patch(axis.line, config.maxScrollSpeed);648        describe('moving forward to end of droppable', () => {649          const onStartBoundary: Position = patch(650            axis.line,651            // to the boundary is not enough to start652            (frame[axis.size] - thresholds.startFrom),653            frame.center[axis.crossAxisLine],654          );655          const onMaxBoundary: Position = patch(656            axis.line,657            (frame[axis.size] - thresholds.maxSpeedAt),658            frame.center[axis.crossAxisLine],659          );660          const onEndOfFrame: Position = patch(661            axis.line,662            frame[axis.size],663            frame.center[axis.crossAxisLine],664          );665          it('should not scroll if not past the start threshold', () => {666            autoScroller.onStateChange(667              state.idle,668              addDroppable(dragTo({669                selection: onStartBoundary,670                viewport: unscrollableViewport,671              }), scrollable)672            );673            requestAnimationFrame.flush();674            expect(mocks.scrollDroppable).not.toHaveBeenCalled();675          });676          it('should scroll if moving beyond the start threshold', () => {677            const target: Position = add(onStartBoundary, patch(axis.line, 1));678            autoScroller.onStateChange(679              state.idle,680              addDroppable(dragTo({681                selection: target,682                viewport: unscrollableViewport,683              }), scrollable),684            );685            expect(mocks.scrollDroppable).not.toHaveBeenCalled();686            // only called after a frame687            requestAnimationFrame.step();688            expect(mocks.scrollDroppable).toHaveBeenCalled();689            // moving forwards690            const [id, scroll] = mocks.scrollDroppable.mock.calls[0];691            expect(id).toBe(scrollable.descriptor.id);692            expect(scroll[axis.line]).toBeGreaterThan(0);693            expect(scroll[axis.crossAxisLine]).toBe(0);694          });695          it('should throttle multiple scrolls into a single animation frame', () => {696            const target1: Position = add(onStartBoundary, patch(axis.line, 1));697            const target2: Position = add(onStartBoundary, patch(axis.line, 2));698            autoScroller.onStateChange(699              state.idle,700              addDroppable(dragTo({701                selection: target1,702                viewport: unscrollableViewport,703              }), scrollable),704            );705            autoScroller.onStateChange(706              addDroppable(dragTo({707                selection: target1,708                viewport: unscrollableViewport,709              }), scrollable),710              addDroppable(dragTo({711                selection: target2,712                viewport: unscrollableViewport,713              }), scrollable),714            );715            expect(mocks.scrollDroppable).not.toHaveBeenCalled();716            // only called after a frame717            requestAnimationFrame.step();718            expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);719            // verification720            requestAnimationFrame.flush();721            expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);722            // not testing value called as we are not exposing getRequired scroll723          });724          it('should get faster the closer to the max speed point', () => {725            const target1: Position = add(onStartBoundary, patch(axis.line, 1));726            const target2: Position = add(onStartBoundary, patch(axis.line, 2));727            autoScroller.onStateChange(728              state.idle,729              addDroppable(dragTo({730                selection: target1,731                viewport: unscrollableViewport,732              }), scrollable),733            );734            requestAnimationFrame.step();735            expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);736            const scroll1: Position = (mocks.scrollDroppable.mock.calls[0][1] : any);737            autoScroller.onStateChange(738              addDroppable(dragTo({739                selection: target1,740                viewport: unscrollableViewport,741              }), scrollable),742              addDroppable(dragTo({743                selection: target2,744                viewport: unscrollableViewport,745              }), scrollable),746            );747            requestAnimationFrame.step();748            expect(mocks.scrollDroppable).toHaveBeenCalledTimes(2);749            const scroll2: Position = (mocks.scrollDroppable.mock.calls[1][1] : any);750            expect(scroll1[axis.line]).toBeLessThan(scroll2[axis.line]);751            // validation752            expect(scroll1[axis.crossAxisLine]).toBe(0);753            expect(scroll2[axis.crossAxisLine]).toBe(0);754          });755          it('should have the top speed at the max speed point', () => {756            const expected: Position = patch(axis.line, config.maxScrollSpeed);757            autoScroller.onStateChange(758              state.idle,759              addDroppable(dragTo({760                selection: onMaxBoundary,761                viewport: unscrollableViewport,762              }), scrollable),763            );764            requestAnimationFrame.step();765            expect(mocks.scrollDroppable).toHaveBeenCalledWith(766              scrollable.descriptor.id,767              expected768            );769          });770          it('should have the top speed when moving beyond the max speed point', () => {771            const target: Position = add(onMaxBoundary, patch(axis.line, 1));772            const expected: Position = patch(axis.line, config.maxScrollSpeed);773            autoScroller.onStateChange(774              state.idle,775              addDroppable(dragTo({776                selection: target,777                viewport: unscrollableViewport,778              }), scrollable),779            );780            requestAnimationFrame.step();781            expect(mocks.scrollDroppable).toHaveBeenCalledWith(782              scrollable.descriptor.id,783              expected784            );785          });786          it('should allow scrolling to the end of the droppable', () => {787            const target: Position = onEndOfFrame;788            // scrolling to max scroll point789            const maxChange: Position = getClosestScrollable(scrollable).scroll.max;790            const scrolled: DroppableDimension = scrollDroppable(scrollable, maxChange);791            autoScroller.onStateChange(792              state.idle,793              addDroppable(dragTo({794                selection: target,795                viewport: unscrollableViewport,796              }), scrolled),797            );798            requestAnimationFrame.flush();799            expect(mocks.scrollDroppable).not.toHaveBeenCalled();800          });801          describe('big draggable', () => {802            const onMaxBoundaryOfBoth: Position = patch(803              axis.line,804              (frame[axis.size] - thresholds.maxSpeedAt),805              (frame[axis.crossAxisSize] - crossAxisThresholds.maxSpeedAt),806            );807            describe('bigger on the main axis', () => {808              it('should not allow scrolling on the main axis, but allow scrolling on the cross axis', () => {809                const expanded: Area = getArea(expandByPosition(frame, patch(axis.line, 1)));810                const tooBigOnMainAxis: DraggableDimension = getDraggableDimension({811                  descriptor: {812                    id: 'too big',813                    droppableId: preset.home.descriptor.id,814                    // after the last item815                    index: preset.inHomeList.length,816                  },817                  paddingBox: expanded,818                });819                const selection: Position = onMaxBoundaryOfBoth;820                const custom: State = (() => {821                  const base: State = state.dragging(822                    preset.inHome1.descriptor.id,823                    selection,824                    unscrollableViewport,825                  );826                  const updated: State = {827                    ...base,828                    drag: {829                      ...base.drag,830                      initial: {831                        // $ExpectError832                        ...base.drag.initial,833                        descriptor: tooBigOnMainAxis.descriptor,834                      },835                    },836                  };837                  return addDroppable(addDraggable(updated, tooBigOnMainAxis), scrollable);838                })();839                autoScroller.onStateChange(state.idle, custom);840                requestAnimationFrame.flush();841                expect(mocks.scrollDroppable).toHaveBeenCalledWith(842                  scrollable.descriptor.id,843                  // scroll ocurred on the cross axis, but not on the main axis844                  patch(axis.crossAxisLine, config.maxScrollSpeed)845                );846              });847            });848            describe('bigger on the cross axis', () => {849              it('should not allow scrolling on the cross axis, but allow scrolling on the main axis', () => {850                const expanded: Area = getArea(851                  expandByPosition(frame, patch(axis.crossAxisLine, 1))852                );853                const tooBigOnCrossAxis: DraggableDimension = getDraggableDimension({854                  descriptor: {855                    id: 'too big',856                    droppableId: preset.home.descriptor.id,857                    // after the last item858                    index: preset.inHomeList.length,859                  },860                  paddingBox: expanded,861                });862                const selection: Position = onMaxBoundaryOfBoth;863                const custom: State = (() => {864                  const base: State = state.dragging(865                    preset.inHome1.descriptor.id,866                    selection,867                    unscrollableViewport,868                  );869                  const updated: State = {870                    ...base,871                    drag: {872                      ...base.drag,873                      initial: {874                        // $ExpectError875                        ...base.drag.initial,876                        descriptor: tooBigOnCrossAxis.descriptor,877                      },878                    },879                  };880                  return addDroppable(addDraggable(updated, tooBigOnCrossAxis), scrollable);881                })();882                autoScroller.onStateChange(state.idle, custom);883                requestAnimationFrame.flush();884                expect(mocks.scrollDroppable).toHaveBeenCalledWith(885                  scrollable.descriptor.id,886                  // scroll ocurred on the main axis, but not on the cross axis887                  patch(axis.line, config.maxScrollSpeed)888                );889              });890            });891            describe('bigger on both axis', () => {892              it('should not allow scrolling on the cross axis, but allow scrolling on the main axis', () => {893                const expanded: Area = getArea(894                  expandByPosition(frame, patch(axis.line, 1, 1))895                );896                const tooBig: DraggableDimension = getDraggableDimension({897                  descriptor: {898                    id: 'too big',899                    droppableId: preset.home.descriptor.id,900                    // after the last item901                    index: preset.inHomeList.length,902                  },903                  paddingBox: expanded,904                });905                const selection: Position = onMaxBoundaryOfBoth;906                const custom: State = (() => {907                  const base: State = state.dragging(908                    preset.inHome1.descriptor.id,909                    selection,910                    unscrollableViewport,911                  );912                  const updated: State = {913                    ...base,914                    drag: {915                      ...base.drag,916                      initial: {917                        // $ExpectError918                        ...base.drag.initial,919                        descriptor: tooBig.descriptor,920                      },921                    },922                  };923                  return addDroppable(addDraggable(updated, tooBig), scrollable);924                })();925                autoScroller.onStateChange(state.idle, custom);926                requestAnimationFrame.step();927                expect(mocks.scrollDroppable).not.toHaveBeenCalled();928              });929            });930          });931          describe('over home list', () => {932            it('should not scroll if the droppable if moving past the end of the frame', () => {933              const target: Position = add(onEndOfFrame, patch(axis.line, 1));934              // scrolling to max scroll point935              const maxChange: Position = getClosestScrollable(scrollable).scroll.max;936              const scrolled: DroppableDimension = scrollDroppable(scrollable, maxChange);937              autoScroller.onStateChange(938                state.idle,939                addDroppable(dragTo({940                  selection: target,941                  viewport: unscrollableViewport,942                }), scrolled),943              );944              requestAnimationFrame.flush();945              expect(mocks.scrollDroppable).not.toHaveBeenCalled();946            });947          });948          describe('over foreign list', () => {949            // $ExpectError - using spread950            const foreign: DroppableDimension = {951              ...scrollable,952              descriptor: preset.foreign.descriptor,953            };954            const placeholder: Position = patch(955              axis.line,956              preset.inHome1.placeholder.paddingBox[axis.size],957            );958            const overForeign: DragImpact = {959              movement: noMovement,960              direction: foreign.axis.direction,961              destination: {962                index: 0,963                droppableId: foreign.descriptor.id,964              },965            };966            it('should allow scrolling up to the end of the frame + the size of the placeholder', () => {967              // scrolling to just before the end of the placeholder968              // this goes beyond the usual max scroll.969              const scroll: Position = add(970                // usual max scroll971                getClosestScrollable(foreign).scroll.max,972                // with a small bit of room towards the end of the placeholder space973                subtract(placeholder, patch(axis.line, 1))974              );975              const scrolledForeign: DroppableDimension = scrollDroppable(foreign, scroll);976              const target: Position = add(onEndOfFrame, placeholder);977              const expected: Position = patch(axis.line, config.maxScrollSpeed);978              autoScroller.onStateChange(979                state.idle,980                addDroppable(dragTo({981                  selection: target,982                  impact: overForeign,983                  viewport: unscrollableViewport,984                }), scrolledForeign),985              );986              requestAnimationFrame.step();987              expect(mocks.scrollDroppable).toHaveBeenCalledWith(foreign.descriptor.id, expected);988            });989            it('should not allow scrolling past the placeholder buffer', () => {990              // already on the placeholder991              const scroll: Position = add(992                // usual max scroll993                getClosestScrollable(foreign).scroll.max,994                // with the placeholder995                placeholder,996              );997              const scrolledForeign: DroppableDimension = scrollDroppable(foreign, scroll);998              // targeting beyond the placeholder999              const target: Position = add(1000                add(onEndOfFrame, placeholder),1001                patch(axis.line, 1),1002              );1003              autoScroller.onStateChange(1004                state.idle,1005                addDroppable(dragTo({1006                  selection: target,1007                  impact: overForeign,1008                  viewport: unscrollableViewport,1009                }), scrolledForeign),1010              );1011              requestAnimationFrame.flush();1012              expect(mocks.scrollDroppable).not.toHaveBeenCalled();1013            });1014          });1015        });1016        describe('moving backward to the start of droppable', () => {1017          const droppableScroll: Position = patch(axis.line, 10);1018          const scrolled: DroppableDimension = scrollDroppable(scrollable, droppableScroll);1019          const onStartBoundary: Position = patch(1020            axis.line,1021            // to the boundary is not enough to start1022            (frame[axis.start] + thresholds.startFrom),1023            frame.center[axis.crossAxisLine],1024          );1025          const onMaxBoundary: Position = patch(1026            axis.line,1027            (frame[axis.start] + thresholds.maxSpeedAt),1028            frame.center[axis.crossAxisLine],1029          );1030          it('should not scroll if not past the start threshold', () => {1031            autoScroller.onStateChange(1032              state.idle,1033              addDroppable(dragTo({1034                selection: onStartBoundary,1035                viewport: unscrollableViewport,1036              }), scrolled)1037            );1038            requestAnimationFrame.flush();1039            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1040          });1041          it('should scroll if moving beyond the start threshold', () => {1042            // going backwards1043            const target: Position = subtract(onStartBoundary, patch(axis.line, 1));1044            autoScroller.onStateChange(1045              state.idle,1046              addDroppable(dragTo({1047                selection: target,1048                viewport: unscrollableViewport,1049              }), scrolled),1050            );1051            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1052            // only called after a frame1053            requestAnimationFrame.step();1054            expect(mocks.scrollDroppable).toHaveBeenCalled();1055            const [id, scroll] = mocks.scrollDroppable.mock.calls[0];1056            // validation1057            expect(id).toBe(scrollable.descriptor.id);1058            // moving backwards1059            expect(scroll[axis.line]).toBeLessThan(0);1060            expect(scroll[axis.crossAxisLine]).toBe(0);1061          });1062          it('should throttle multiple scrolls into a single animation frame', () => {1063            const target1: Position = subtract(onStartBoundary, patch(axis.line, 1));1064            const target2: Position = subtract(onStartBoundary, patch(axis.line, 2));1065            autoScroller.onStateChange(1066              state.idle,1067              addDroppable(dragTo({1068                selection: target1,1069                viewport: unscrollableViewport,1070              }), scrolled),1071            );1072            autoScroller.onStateChange(1073              addDroppable(dragTo({1074                selection: target1,1075                viewport: unscrollableViewport,1076              }), scrolled),1077              addDroppable(dragTo({1078                selection: target2,1079                viewport: unscrollableViewport,1080              }), scrolled),1081            );1082            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1083            // only called after a frame1084            requestAnimationFrame.step();1085            expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);1086            // verification1087            requestAnimationFrame.flush();1088            expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);1089            // not testing value called as we are not exposing getRequired scroll1090          });1091          it('should get faster the closer to the max speed point', () => {1092            const target1: Position = subtract(onStartBoundary, patch(axis.line, 1));1093            const target2: Position = subtract(onStartBoundary, patch(axis.line, 2));1094            autoScroller.onStateChange(1095              state.idle,1096              addDroppable(dragTo({1097                selection: target1,1098                viewport: unscrollableViewport,1099              }), scrolled),1100            );1101            requestAnimationFrame.step();1102            expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);1103            const scroll1: Position = (mocks.scrollDroppable.mock.calls[0][1] : any);1104            autoScroller.onStateChange(1105              addDroppable(dragTo({1106                selection: target1,1107                viewport: unscrollableViewport,1108              }), scrolled),1109              addDroppable(dragTo({1110                selection: target2,1111                viewport: unscrollableViewport,1112              }), scrolled),1113            );1114            requestAnimationFrame.step();1115            expect(mocks.scrollDroppable).toHaveBeenCalledTimes(2);1116            const scroll2: Position = (mocks.scrollDroppable.mock.calls[1][1] : any);1117            // moving backwards1118            expect(scroll1[axis.line]).toBeGreaterThan(scroll2[axis.line]);1119            // validation1120            expect(scroll1[axis.crossAxisLine]).toBe(0);1121            expect(scroll2[axis.crossAxisLine]).toBe(0);1122          });1123          it('should have the top speed at the max speed point', () => {1124            const expected: Position = patch(axis.line, -config.maxScrollSpeed);1125            autoScroller.onStateChange(1126              state.idle,1127              addDroppable(dragTo({1128                selection: onMaxBoundary,1129                viewport: unscrollableViewport,1130              }), scrolled),1131            );1132            requestAnimationFrame.step();1133            expect(mocks.scrollDroppable).toHaveBeenCalledWith(1134              scrollable.descriptor.id,1135              expected1136            );1137          });1138          it('should have the top speed when moving beyond the max speed point', () => {1139            const target: Position = subtract(onMaxBoundary, patch(axis.line, 1));1140            const expected: Position = patch(axis.line, -config.maxScrollSpeed);1141            autoScroller.onStateChange(1142              state.idle,1143              addDroppable(dragTo({1144                selection: target,1145                viewport: unscrollableViewport,1146              }), scrolled),1147            );1148            requestAnimationFrame.step();1149            expect(mocks.scrollDroppable).toHaveBeenCalledWith(1150              scrollable.descriptor.id,1151              expected1152            );1153          });1154          it('should not scroll if the item is too big', () => {1155            const expanded: Area = getArea(expandByPosition(frame, { x: 1, y: 1 }));1156            const tooBig: DraggableDimension = getDraggableDimension({1157              descriptor: {1158                id: 'too big',1159                droppableId: preset.home.descriptor.id,1160                // after the last item1161                index: preset.inHomeList.length,1162              },1163              paddingBox: expanded,1164            });1165            const selection: Position = onMaxBoundary;1166            const custom: State = (() => {1167              const base: State = state.dragging(1168                preset.inHome1.descriptor.id,1169                selection,1170                unscrollableViewport,1171              );1172              const updated: State = {1173                ...base,1174                drag: {1175                  ...base.drag,1176                  initial: {1177                    // $ExpectError1178                    ...base.drag.initial,1179                    descriptor: tooBig.descriptor,1180                  },1181                },1182              };1183              return addDroppable(addDraggable(updated, tooBig), scrolled);1184            })();1185            autoScroller.onStateChange(state.idle, custom);1186            requestAnimationFrame.flush();1187            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1188          });1189          it('should not scroll if the droppable is unable to be scrolled', () => {1190            const target: Position = onMaxBoundary;1191            if (!scrollable.viewport.closestScrollable) {1192              throw new Error('Invalid test setup');1193            }1194            // scrolling to max scroll point1195            autoScroller.onStateChange(1196              state.idle,1197              // scrollable cannot be scrolled backwards1198              addDroppable(dragTo({1199                selection: target,1200                viewport: unscrollableViewport,1201              }), scrollable)1202            );1203            requestAnimationFrame.flush();1204            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1205          });1206        });1207        // just some light tests to ensure that cross axis moving also works1208        describe('moving forward on the cross axis', () => {1209          const droppableScroll: Position = patch(axis.crossAxisLine, 10);1210          const scrolled: DroppableDimension = scrollDroppable(scrollable, droppableScroll);1211          const onStartBoundary: Position = patch(1212            axis.line,1213            frame.center[axis.line],1214            // to the boundary is not enough to start1215            (frame[axis.crossAxisSize] - crossAxisThresholds.startFrom),1216          );1217          it('should not scroll if not past the start threshold', () => {1218            autoScroller.onStateChange(state.idle, dragTo({1219              selection: onStartBoundary,1220              viewport: unscrollableViewport,1221            }));1222            requestAnimationFrame.flush();1223            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1224          });1225          it('should scroll if moving beyond the start threshold', () => {1226            const target: Position = add(onStartBoundary, patch(axis.crossAxisLine, 1));1227            autoScroller.onStateChange(1228              state.idle,1229              addDroppable(dragTo({1230                selection: target,1231                viewport: unscrollableViewport,1232              }), scrolled),1233            );1234            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1235            // only called after a frame1236            requestAnimationFrame.step();1237            expect(mocks.scrollDroppable).toHaveBeenCalled();1238            // moving forwards1239            const [id, scroll] = mocks.scrollDroppable.mock.calls[0];1240            expect(id).toBe(scrolled.descriptor.id);1241            expect(scroll[axis.crossAxisLine]).toBeGreaterThan(0);1242          });1243        });1244        // just some light tests to ensure that cross axis moving also works1245        describe('moving backward on the cross axis', () => {1246          const droppableScroll: Position = patch(axis.crossAxisLine, 10);1247          const scrolled: DroppableDimension = scrollDroppable(scrollable, droppableScroll);1248          const onStartBoundary: Position = patch(1249            axis.line,1250            frame.center[axis.line],1251            // to the boundary is not enough to start1252            (frame[axis.crossAxisStart] + crossAxisThresholds.startFrom)1253          );1254          it('should not scroll if not past the start threshold', () => {1255            autoScroller.onStateChange(1256              state.idle,1257              addDroppable(dragTo({1258                selection: onStartBoundary,1259                viewport: unscrollableViewport,1260              }), scrolled),1261            );1262            requestAnimationFrame.flush();1263            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1264          });1265          it('should scroll if moving beyond the start threshold', () => {1266            const target: Position = subtract(onStartBoundary, patch(axis.crossAxisLine, 1));1267            autoScroller.onStateChange(1268              state.idle,1269              addDroppable(dragTo({1270                selection: target,1271                viewport: unscrollableViewport,1272              }), scrolled),1273            );1274            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1275            // only called after a frame1276            requestAnimationFrame.step();1277            expect(mocks.scrollDroppable).toHaveBeenCalled();1278            // moving backwards1279            const request: Position = mocks.scrollDroppable.mock.calls[0][1];1280            expect(request[axis.crossAxisLine]).toBeLessThan(0);1281          });1282        });1283        describe('over frame but not a subject', () => {1284          const withSmallSubject: DroppableDimension = getDroppableDimension({1285            // stealing the home descriptor1286            descriptor: preset.home.descriptor,1287            direction: axis.direction,1288            paddingBox: getArea({1289              top: 0,1290              left: 0,1291              right: 100,1292              bottom: 100,1293            }),1294            closest: {1295              framePaddingBox: getArea({1296                top: 0,1297                left: 0,1298                right: 5000,1299                bottom: 5000,1300              }),1301              scrollWidth: 10000,1302              scrollHeight: 10000,1303              scroll: origin,1304              shouldClipSubject: true,1305            },1306          });1307          const endOfSubject: Position = patch(axis.line, 100);1308          const endOfFrame: Position = patch(1309            axis.line,1310            // on the end1311            5000,1312            // half way1313            2500,1314          );1315          it('should scroll a frame if it is being dragged over, even if not over the subject', () => {1316            const scrolled: DroppableDimension = scrollDroppable(1317              withSmallSubject,1318              // scrolling the whole client away1319              endOfSubject,1320            );1321            // subject no longer visible1322            expect(scrolled.viewport.clipped).toBe(null);1323            // const target: Position = add(endOfFrame, patch(axis.line, 1));1324            autoScroller.onStateChange(1325              state.idle,1326              withImpact(1327                addDroppable(dragTo({1328                  selection: endOfFrame,1329                  viewport: unscrollableViewport,1330                }), scrolled),1331                // being super clear that we are not currently over any droppable1332                noImpact,1333              )1334            );1335            requestAnimationFrame.step();1336            expect(mocks.scrollDroppable).toHaveBeenCalledWith(1337              scrolled.descriptor.id,1338              maxScrollSpeed,1339            );1340          });1341          it('should not scroll the frame if not over the frame', () => {1342            const scrolled: DroppableDimension = scrollDroppable(1343              withSmallSubject,1344              // scrolling the whole client away1345              endOfSubject,1346            );1347            // subject no longer visible1348            expect(scrolled.viewport.clipped).toBe(null);1349            const target: Position = add(endOfFrame, patch(axis.line, 1));1350            autoScroller.onStateChange(1351              state.idle,1352              withImpact(1353                addDroppable(dragTo({1354                  selection: target,1355                  viewport: unscrollableViewport,1356                }), scrolled),1357                // being super clear that we are not currently over any droppable1358                noImpact,1359              )1360            );1361            requestAnimationFrame.step();1362            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1363          });1364        });1365      });1366      describe('window scrolling before droppable scrolling', () => {1367        const custom: DroppableDimension = getDroppableDimension({1368          descriptor: {1369            id: 'scrollable that is similiar to the viewport',1370            type: 'TYPE',1371          },1372          paddingBox: getArea({1373            top: 0,1374            left: 0,1375            // bigger than the frame1376            right: windowScrollSize.scrollWidth,1377            bottom: windowScrollSize.scrollHeight,1378          }),1379          closest: {1380            framePaddingBox: scrollableViewport.subject,1381            scrollWidth: windowScrollSize.scrollWidth,1382            scrollHeight: windowScrollSize.scrollHeight,1383            scroll: origin,1384            shouldClipSubject: true,1385          },1386        });1387        const thresholds: PixelThresholds = getPixelThresholds(scrollableViewport.subject, axis);1388        it('should scroll the window only if both the window and droppable can be scrolled', () => {1389          const onMaxBoundary: Position = patch(1390            axis.line,1391            (scrollableViewport.subject[axis.size] - thresholds.maxSpeedAt),1392            scrollableViewport.subject.center[axis.crossAxisLine],1393          );1394          autoScroller.onStateChange(1395            state.idle,1396            addDroppable(dragTo({1397              selection: onMaxBoundary,1398              viewport: scrollableViewport,1399            }), custom),1400          );1401          requestAnimationFrame.step();1402          expect(mocks.scrollWindow).toHaveBeenCalled();1403          expect(mocks.scrollDroppable).not.toHaveBeenCalled();1404        });1405      });1406      describe('on drag end', () => {1407        const endDragStates = [1408          state.idle,1409          state.dropAnimating(),1410          state.userCancel(),1411          state.dropComplete(),1412        ];1413        endDragStates.forEach((end: State) => {1414          it('should cancel any pending window scroll', () => {1415            const thresholds: PixelThresholds = getPixelThresholds(1416              scrollableViewport.subject, axis1417            );1418            const onMaxBoundary: Position = patch(1419              axis.line,1420              (scrollableViewport.subject[axis.size] - thresholds.maxSpeedAt),1421              scrollableViewport.subject.center[axis.crossAxisLine],1422            );1423            autoScroller.onStateChange(state.idle, dragTo({1424              selection: onMaxBoundary,1425              viewport: scrollableViewport,1426            }));1427            // frame not cleared1428            expect(mocks.scrollWindow).not.toHaveBeenCalled();1429            // should cancel the next frame1430            autoScroller.onStateChange(dragTo({1431              selection: onMaxBoundary,1432              viewport: scrollableViewport,1433            }), end);1434            requestAnimationFrame.flush();1435            expect(mocks.scrollWindow).not.toHaveBeenCalled();1436          });1437          it('should cancel any pending droppable scroll', () => {1438            const thresholds: PixelThresholds = getPixelThresholds(frame, axis);1439            const onMaxBoundary: Position = patch(1440              axis.line,1441              (frame[axis.size] - thresholds.maxSpeedAt),1442              frame.center[axis.crossAxisLine],1443            );1444            const drag: State = addDroppable(dragTo({1445              selection: onMaxBoundary,1446              viewport: scrollableViewport,1447            }), scrollable);1448            autoScroller.onStateChange(1449              state.idle,1450              drag1451            );1452            // frame not cleared1453            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1454            // should cancel the next frame1455            autoScroller.onStateChange(drag, end);1456            requestAnimationFrame.flush();1457            expect(mocks.scrollDroppable).not.toHaveBeenCalled();1458          });...droppable-scrolling.spec.js
Source:droppable-scrolling.spec.js  
...43      patch(axis.line, 1),44    );45    const startWithNoScroll = (scroller: FluidScroller) => {46      scroller.start(47        dragTo({48          selection: noScrollTarget,49          viewport: unscrollableViewport,50          droppable: scrollable,51          state,52        }),53      );54      requestAnimationFrame.step();55    };56    it('should not scroll if before the start threshold', () => {57      const mocks = getArgsMock();58      const scroller: FluidScroller = getScroller(mocks);59      const target: Position = subtract(onStartBoundary, patch(axis.line, 1));60      scroller.start(61        dragTo({62          selection: target,63          viewport: unscrollableViewport,64          droppable: scrollable,65          state,66        }),67      );68      requestAnimationFrame.flush();69      expect(mocks.scrollDroppable).not.toHaveBeenCalled();70    });71    it('should scroll if on the start threshold', () => {72      const mocks = getArgsMock();73      const scroller: FluidScroller = getScroller(mocks);74      scroller.start(75        dragTo({76          selection: onStartBoundary,77          viewport: unscrollableViewport,78          droppable: scrollable,79          state,80        }),81      );82      expect(mocks.scrollDroppable).not.toHaveBeenCalled();83      requestAnimationFrame.step();84      expect(mocks.scrollDroppable).toHaveBeenCalled();85    });86    it('should scroll if moving beyond the start threshold', () => {87      const mocks = getArgsMock();88      const scroller: FluidScroller = getScroller(mocks);89      const target: Position = add(onStartBoundary, patch(axis.line, 1));90      scroller.start(91        dragTo({92          selection: target,93          viewport: unscrollableViewport,94          droppable: scrollable,95          state,96        }),97      );98      expect(mocks.scrollDroppable).not.toHaveBeenCalled();99      // only called after a frame100      requestAnimationFrame.step();101      expect(mocks.scrollDroppable).toHaveBeenCalled();102      // moving forwards103      const id: DroppableId = mocks.scrollDroppable.mock.calls[0][0];104      const request: Position = mocks.scrollDroppable.mock.calls[0][1];105      expect(id).toEqual(scrollable.descriptor.id);106      expect(request[axis.line]).toBeGreaterThan(0);107    });108    it('should get faster the closer to the max speed point', () => {109      const mocks = getArgsMock();110      const scroller: FluidScroller = getScroller(mocks);111      const atStartOfRange: Position = onStartBoundary;112      const atEndOfRange: Position = subtract(113        onMaxBoundary,114        patch(axis.line, 1),115      );116      // start the drag with no auto scrolling117      // this will opt out of time dampening118      startWithNoScroll(scroller);119      expect(mocks.scrollDroppable).not.toHaveBeenCalled();120      scroller.scroll(121        dragTo({122          selection: atStartOfRange,123          viewport: unscrollableViewport,124          droppable: scrollable,125          state,126        }),127      );128      requestAnimationFrame.step();129      expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);130      const scroll1: Position = (mocks.scrollDroppable.mock.calls[0][1]: any);131      scroller.scroll(132        dragTo({133          selection: atEndOfRange,134          viewport: unscrollableViewport,135          droppable: scrollable,136          state,137        }),138      );139      requestAnimationFrame.step();140      expect(mocks.scrollDroppable).toHaveBeenCalledTimes(2);141      const scroll2: Position = (mocks.scrollDroppable.mock.calls[1][1]: any);142      expect(scroll1[axis.line]).toBeLessThan(scroll2[axis.line]);143      // validation144      expect(scroll1[axis.crossAxisLine]).toBe(0);145      expect(scroll2[axis.crossAxisLine]).toBe(0);146    });147    it('should have the top speed at the max speed point', () => {148      const mocks = getArgsMock();149      const scroller: FluidScroller = getScroller(mocks);150      startWithNoScroll(scroller);151      scroller.scroll(152        dragTo({153          selection: onMaxBoundary,154          viewport: unscrollableViewport,155          droppable: scrollable,156          state,157        }),158      );159      requestAnimationFrame.step();160      expect(mocks.scrollDroppable).toHaveBeenCalledWith(161        scrollable.descriptor.id,162        patch(axis.line, config.maxPixelScroll),163      );164    });165    it('should have the top speed when moving beyond the max speed point', () => {166      const mocks = getArgsMock();167      const scroller: FluidScroller = getScroller(mocks);168      const target: Position = add(onMaxBoundary, patch(axis.line, 1));169      startWithNoScroll(scroller);170      scroller.scroll(171        dragTo({172          selection: target,173          viewport: unscrollableViewport,174          droppable: scrollable,175          state,176        }),177      );178      requestAnimationFrame.step();179      expect(mocks.scrollDroppable).toHaveBeenCalledWith(180        scrollable.descriptor.id,181        patch(axis.line, config.maxPixelScroll),182      );183    });184    it('should throttle multiple scrolls into a single animation frame', () => {185      const mocks = getArgsMock();186      const scroller: FluidScroller = getScroller(mocks);187      const target1: Position = add(onStartBoundary, patch(axis.line, 1));188      const target2: Position = subtract(onMaxBoundary, patch(axis.line, 1));189      startWithNoScroll(scroller);190      scroller.scroll(191        dragTo({192          selection: target1,193          viewport: unscrollableViewport,194          droppable: scrollable,195          state,196        }),197      );198      scroller.scroll(199        dragTo({200          selection: target2,201          viewport: unscrollableViewport,202          droppable: scrollable,203          state,204        }),205      );206      requestAnimationFrame.step();207      expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);208      expect(mocks.scrollDroppable).toHaveBeenCalledWith(209        scrollable.descriptor.id,210        patch(axis.line, config.maxPixelScroll),211      );212    });213  });214  describe('moving backward to start of droppable', () => {215    const droppableScroll: Position = patch(axis.line, 10);216    const scrolled: DroppableDimension = scrollDroppable(217      scrollable,218      droppableScroll,219    );220    const onStartBoundary: Position = patch(221      axis.line,222      // at the boundary is not enough to start223      frameClient.borderBox[axis.start] + thresholds.startScrollingFrom,224      frameClient.borderBox.center[axis.crossAxisLine],225    );226    const onMaxBoundary: Position = patch(227      axis.line,228      frameClient.borderBox[axis.start] + thresholds.maxScrollValueAt,229      frameClient.borderBox.center[axis.crossAxisLine],230    );231    const noScrollTarget: Position = add(onStartBoundary, patch(axis.line, 1));232    const startWithNoScroll = (scroller: FluidScroller) => {233      scroller.start(234        dragTo({235          selection: noScrollTarget,236          viewport: unscrollableViewport,237          droppable: scrolled,238          state,239        }),240      );241      requestAnimationFrame.step();242    };243    it('should not scroll if before the start threshold', () => {244      const mocks = getArgsMock();245      const scroller: FluidScroller = getScroller(mocks);246      const target: Position = add(onStartBoundary, patch(axis.line, 1));247      scroller.start(248        dragTo({249          selection: target,250          viewport: unscrollableViewport,251          droppable: scrolled,252          state,253        }),254      );255      requestAnimationFrame.flush();256      expect(mocks.scrollDroppable).not.toHaveBeenCalled();257    });258    it('should scroll if on the start threshold', () => {259      const mocks = getArgsMock();260      const scroller: FluidScroller = getScroller(mocks);261      scroller.start(262        dragTo({263          selection: onStartBoundary,264          viewport: unscrollableViewport,265          droppable: scrolled,266          state,267        }),268      );269      expect(mocks.scrollDroppable).not.toHaveBeenCalled();270      requestAnimationFrame.flush();271      expect(mocks.scrollDroppable).toHaveBeenCalled();272    });273    it('should scroll if moving beyond the start threshold', () => {274      const mocks = getArgsMock();275      const scroller: FluidScroller = getScroller(mocks);276      const target: Position = subtract(onStartBoundary, patch(axis.line, 1));277      scroller.start(278        dragTo({279          selection: target,280          viewport: unscrollableViewport,281          droppable: scrolled,282          state,283        }),284      );285      expect(mocks.scrollDroppable).not.toHaveBeenCalled();286      // only called after a frame287      requestAnimationFrame.step();288      expect(mocks.scrollDroppable).toHaveBeenCalled();289      // moving forwards290      const request: Position = mocks.scrollDroppable.mock.calls[0][1];291      expect(request[axis.line]).toBeLessThan(0);292    });293    it('should get faster the closer to the max speed point', () => {294      const mocks = getArgsMock();295      const scroller: FluidScroller = getScroller(mocks);296      const atStartOfRange: Position = onStartBoundary;297      const atEndOfRange: Position = add(onMaxBoundary, patch(axis.line, 1));298      // start the drag with no auto scrolling299      // this will opt out of time dampening300      startWithNoScroll(scroller);301      expect(mocks.scrollDroppable).not.toHaveBeenCalled();302      scroller.scroll(303        dragTo({304          selection: atStartOfRange,305          viewport: unscrollableViewport,306          droppable: scrolled,307          state,308        }),309      );310      requestAnimationFrame.step();311      expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);312      const scroll1: Position = (mocks.scrollDroppable.mock.calls[0][1]: any);313      scroller.scroll(314        dragTo({315          selection: atEndOfRange,316          viewport: unscrollableViewport,317          droppable: scrolled,318          state,319        }),320      );321      requestAnimationFrame.step();322      expect(mocks.scrollDroppable).toHaveBeenCalledTimes(2);323      const scroll2: Position = (mocks.scrollDroppable.mock.calls[1][1]: any);324      expect(scroll1[axis.line]).toBeGreaterThan(scroll2[axis.line]);325      // validation326      expect(scroll1[axis.crossAxisLine]).toBe(0);327      expect(scroll2[axis.crossAxisLine]).toBe(0);328    });329    it('should have the top speed at the max speed point', () => {330      const mocks = getArgsMock();331      const scroller: FluidScroller = getScroller(mocks);332      startWithNoScroll(scroller);333      scroller.scroll(334        dragTo({335          selection: onMaxBoundary,336          viewport: unscrollableViewport,337          droppable: scrolled,338          state,339        }),340      );341      requestAnimationFrame.step();342      expect(mocks.scrollDroppable).toHaveBeenCalledWith(343        scrolled.descriptor.id,344        negate(patch(axis.line, config.maxPixelScroll)),345      );346    });347    it('should have the top speed when moving beyond the max speed point', () => {348      const mocks = getArgsMock();349      const scroller: FluidScroller = getScroller(mocks);350      const target: Position = subtract(onMaxBoundary, patch(axis.line, 1));351      startWithNoScroll(scroller);352      scroller.scroll(353        dragTo({354          selection: target,355          viewport: unscrollableViewport,356          droppable: scrolled,357          state,358        }),359      );360      requestAnimationFrame.step();361      expect(mocks.scrollDroppable).toHaveBeenCalledWith(362        scrolled.descriptor.id,363        negate(patch(axis.line, config.maxPixelScroll)),364      );365    });366    it('should throttle multiple scrolls into a single animation frame', () => {367      const mocks = getArgsMock();368      const scroller: FluidScroller = getScroller(mocks);369      const target1: Position = subtract(onStartBoundary, patch(axis.line, 1));370      const target2: Position = add(onMaxBoundary, patch(axis.line, 1));371      startWithNoScroll(scroller);372      scroller.scroll(373        dragTo({374          selection: target1,375          viewport: unscrollableViewport,376          droppable: scrolled,377          state,378        }),379      );380      scroller.scroll(381        dragTo({382          selection: target2,383          viewport: unscrollableViewport,384          droppable: scrolled,385          state,386        }),387      );388      requestAnimationFrame.step();389      expect(mocks.scrollDroppable).toHaveBeenCalledTimes(1);390      expect(mocks.scrollDroppable).toHaveBeenCalledWith(391        scrolled.descriptor.id,392        negate(patch(axis.line, config.maxPixelScroll)),393      );394    });395  });...window-scrolling.spec.js
Source:window-scrolling.spec.js  
...41      patch(axis.line, 1),42    );43    const startWithNoScroll = (scroller: FluidScroller) => {44      scroller.start(45        dragTo({46          selection: noScrollTarget,47          viewport: scrollableViewport,48          state,49        }),50      );51      requestAnimationFrame.step();52    };53    it('should not scroll if before the start threshold', () => {54      const mocks = getArgsMock();55      const scroller: FluidScroller = getScroller(mocks);56      const target: Position = subtract(onStartBoundary, patch(axis.line, 1));57      scroller.start(58        dragTo({59          selection: target,60          viewport: scrollableViewport,61          state,62        }),63      );64      requestAnimationFrame.flush();65      expect(mocks.scrollWindow).not.toHaveBeenCalled();66    });67    it('should scroll if on the start threshold', () => {68      const mocks = getArgsMock();69      const scroller: FluidScroller = getScroller(mocks);70      scroller.start(71        dragTo({72          selection: onStartBoundary,73          viewport: scrollableViewport,74          state,75        }),76      );77      expect(mocks.scrollWindow).not.toHaveBeenCalled();78      requestAnimationFrame.step();79      expect(mocks.scrollWindow).toHaveBeenCalled();80    });81    it('should scroll if moving beyond the start threshold', () => {82      const mocks = getArgsMock();83      const scroller: FluidScroller = getScroller(mocks);84      const target: Position = add(onStartBoundary, patch(axis.line, 1));85      scroller.start(86        dragTo({87          selection: target,88          viewport: scrollableViewport,89          state,90        }),91      );92      expect(mocks.scrollWindow).not.toHaveBeenCalled();93      // only called after a frame94      requestAnimationFrame.step();95      expect(mocks.scrollWindow).toHaveBeenCalled();96      // moving forwards97      const request: Position = mocks.scrollWindow.mock.calls[0][0];98      expect(request[axis.line]).toBeGreaterThan(0);99    });100    it('should get faster the closer to the max speed point', () => {101      const mocks = getArgsMock();102      const scroller: FluidScroller = getScroller(mocks);103      const atStartOfRange: Position = onStartBoundary;104      const atEndOfRange: Position = subtract(105        onMaxBoundary,106        patch(axis.line, 1),107      );108      // start the drag with no auto scrolling109      // this will opt out of time dampening110      startWithNoScroll(scroller);111      expect(mocks.scrollWindow).not.toHaveBeenCalled();112      scroller.scroll(113        dragTo({114          selection: atStartOfRange,115          viewport: scrollableViewport,116          state,117        }),118      );119      requestAnimationFrame.step();120      expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);121      const scroll1: Position = (mocks.scrollWindow.mock.calls[0][0]: any);122      scroller.scroll(123        dragTo({124          selection: atEndOfRange,125          viewport: scrollableViewport,126          state,127        }),128      );129      requestAnimationFrame.step();130      expect(mocks.scrollWindow).toHaveBeenCalledTimes(2);131      const scroll2: Position = (mocks.scrollWindow.mock.calls[1][0]: any);132      expect(scroll1[axis.line]).toBeLessThan(scroll2[axis.line]);133      // validation134      expect(scroll1[axis.crossAxisLine]).toBe(0);135      expect(scroll2[axis.crossAxisLine]).toBe(0);136    });137    it('should have the top speed at the max speed point', () => {138      const mocks = getArgsMock();139      const scroller: FluidScroller = getScroller(mocks);140      startWithNoScroll(scroller);141      scroller.scroll(142        dragTo({143          selection: onMaxBoundary,144          viewport: scrollableViewport,145          state,146        }),147      );148      requestAnimationFrame.step();149      expect(mocks.scrollWindow).toHaveBeenCalledWith(150        patch(axis.line, config.maxPixelScroll),151      );152    });153    it('should have the top speed when moving beyond the max speed point', () => {154      const mocks = getArgsMock();155      const scroller: FluidScroller = getScroller(mocks);156      const target: Position = add(onMaxBoundary, patch(axis.line, 1));157      startWithNoScroll(scroller);158      scroller.scroll(159        dragTo({160          selection: target,161          viewport: scrollableViewport,162          state,163        }),164      );165      requestAnimationFrame.step();166      expect(mocks.scrollWindow).toHaveBeenCalledWith(167        patch(axis.line, config.maxPixelScroll),168      );169    });170    it('should throttle multiple scrolls into a single animation frame', () => {171      const mocks = getArgsMock();172      const scroller: FluidScroller = getScroller(mocks);173      const target1: Position = add(onStartBoundary, patch(axis.line, 1));174      const target2: Position = subtract(onMaxBoundary, patch(axis.line, 1));175      startWithNoScroll(scroller);176      scroller.scroll(177        dragTo({178          selection: target1,179          viewport: scrollableViewport,180          state,181        }),182      );183      scroller.scroll(184        dragTo({185          selection: target2,186          viewport: scrollableViewport,187          state,188        }),189      );190      requestAnimationFrame.step();191      expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);192      expect(mocks.scrollWindow).toHaveBeenCalledWith(193        patch(axis.line, config.maxPixelScroll),194      );195    });196  });197  describe('moving backward to start of window', () => {198    const windowScroll: Position = patch(axis.line, 10);199    const scrolledViewport: Viewport = scrollViewport(200      scrollableViewport,201      windowScroll,202    );203    const onStartBoundary: Position = patch(204      axis.line,205      // at the boundary is not enough to start206      windowScroll[axis.line] + thresholds.startScrollingFrom,207      scrolledViewport.frame.center[axis.crossAxisLine],208    );209    const onMaxBoundary: Position = patch(210      axis.line,211      windowScroll[axis.line] + thresholds.maxScrollValueAt,212      scrolledViewport.frame.center[axis.crossAxisLine],213    );214    const noScrollTarget: Position = add(onStartBoundary, patch(axis.line, 1));215    const startWithNoScroll = (scroller: FluidScroller) => {216      scroller.start(217        dragTo({218          selection: noScrollTarget,219          viewport: scrollableViewport,220          state,221        }),222      );223      requestAnimationFrame.step();224    };225    it('should not scroll if before the start threshold', () => {226      const mocks = getArgsMock();227      const scroller: FluidScroller = getScroller(mocks);228      const target: Position = add(onStartBoundary, patch(axis.line, 1));229      scroller.start(230        dragTo({231          selection: target,232          viewport: scrolledViewport,233          state,234        }),235      );236      requestAnimationFrame.flush();237      expect(mocks.scrollWindow).not.toHaveBeenCalled();238    });239    it('should scroll if on the start threshold', () => {240      const mocks = getArgsMock();241      const scroller: FluidScroller = getScroller(mocks);242      scroller.start(243        dragTo({244          selection: onStartBoundary,245          viewport: scrolledViewport,246          state,247        }),248      );249      expect(mocks.scrollWindow).not.toHaveBeenCalled();250      requestAnimationFrame.flush();251      expect(mocks.scrollWindow).toHaveBeenCalled();252    });253    it('should scroll if moving beyond the start threshold', () => {254      const mocks = getArgsMock();255      const scroller: FluidScroller = getScroller(mocks);256      const target: Position = subtract(onStartBoundary, patch(axis.line, 1));257      scroller.start(258        dragTo({259          selection: target,260          viewport: scrolledViewport,261          state,262        }),263      );264      expect(mocks.scrollWindow).not.toHaveBeenCalled();265      // only called after a frame266      requestAnimationFrame.step();267      expect(mocks.scrollWindow).toHaveBeenCalled();268      // moving forwards269      const request: Position = mocks.scrollWindow.mock.calls[0][0];270      expect(request[axis.line]).toBeLessThan(0);271    });272    it('should get faster the closer to the max speed point', () => {273      const mocks = getArgsMock();274      const scroller: FluidScroller = getScroller(mocks);275      const atStartOfRange: Position = onStartBoundary;276      const atEndOfRange: Position = add(onMaxBoundary, patch(axis.line, 1));277      // start the drag with no auto scrolling278      // this will opt out of time dampening279      startWithNoScroll(scroller);280      expect(mocks.scrollWindow).not.toHaveBeenCalled();281      scroller.scroll(282        dragTo({283          selection: atStartOfRange,284          viewport: scrolledViewport,285          state,286        }),287      );288      requestAnimationFrame.step();289      expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);290      const scroll1: Position = (mocks.scrollWindow.mock.calls[0][0]: any);291      scroller.scroll(292        dragTo({293          selection: atEndOfRange,294          viewport: scrolledViewport,295          state,296        }),297      );298      requestAnimationFrame.step();299      expect(mocks.scrollWindow).toHaveBeenCalledTimes(2);300      const scroll2: Position = (mocks.scrollWindow.mock.calls[1][0]: any);301      expect(scroll1[axis.line]).toBeGreaterThan(scroll2[axis.line]);302      // validation303      expect(scroll1[axis.crossAxisLine]).toBe(0);304      expect(scroll2[axis.crossAxisLine]).toBe(0);305    });306    it('should have the top speed at the max speed point', () => {307      const mocks = getArgsMock();308      const scroller: FluidScroller = getScroller(mocks);309      startWithNoScroll(scroller);310      scroller.scroll(311        dragTo({312          selection: onMaxBoundary,313          viewport: scrolledViewport,314          state,315        }),316      );317      requestAnimationFrame.step();318      expect(mocks.scrollWindow).toHaveBeenCalledWith(319        negate(patch(axis.line, config.maxPixelScroll)),320      );321    });322    it('should have the top speed when moving beyond the max speed point', () => {323      const mocks = getArgsMock();324      const scroller: FluidScroller = getScroller(mocks);325      const target: Position = subtract(onMaxBoundary, patch(axis.line, 1));326      startWithNoScroll(scroller);327      scroller.scroll(328        dragTo({329          selection: target,330          viewport: scrolledViewport,331          state,332        }),333      );334      requestAnimationFrame.step();335      expect(mocks.scrollWindow).toHaveBeenCalledWith(336        negate(patch(axis.line, config.maxPixelScroll)),337      );338    });339    it('should throttle multiple scrolls into a single animation frame', () => {340      const mocks = getArgsMock();341      const scroller: FluidScroller = getScroller(mocks);342      const target1: Position = subtract(onStartBoundary, patch(axis.line, 1));343      const target2: Position = add(onMaxBoundary, patch(axis.line, 1));344      startWithNoScroll(scroller);345      scroller.scroll(346        dragTo({347          selection: target1,348          viewport: scrolledViewport,349          state,350        }),351      );352      scroller.scroll(353        dragTo({354          selection: target2,355          viewport: scrolledViewport,356          state,357        }),358      );359      requestAnimationFrame.step();360      expect(mocks.scrollWindow).toHaveBeenCalledTimes(1);361      expect(mocks.scrollWindow).toHaveBeenCalledWith(362        negate(patch(axis.line, config.maxPixelScroll)),363      );364    });365  });...draggingSpec.js
Source:draggingSpec.js  
...3    this.addMatchers(matchers);4  });5  it("should move handle along with mouse after pressing", function() {6    helpers.initDragdealer('simple-slider');7    helpers.dragTo('simple-slider', 100, 0);8    expect('simple-slider').toHavePosition(100, 0);9  });10  it("should move custom handle along with mouse after pressing", function() {11    helpers.initDragdealer('custom-handle', {12      handleClass: 'custom-handle'13    });14    helpers.dragTo('custom-handle', 100, 0, 'custom-handle');15    expect('custom-handle').toHavePosition(100, 0, 'custom-handle');16  });17  it("should not move disabled Dragdealer", function() {18    helpers.initDragdealer('simple-slider', {19      disabled: true20    });21    helpers.dragTo('simple-slider', 100, 0);22    expect('simple-slider').toHavePosition(0, 0);23  });24  it("should not drag horizontal slider vertically", function() {25    helpers.initDragdealer('square-slider', {26      horizontal: true,27      vertical: false28    });29    helpers.dragTo('square-slider', 0, 100);30    expect('square-slider').toHavePosition(0, 0);31    helpers.dragTo('square-slider', 200, 200);32    expect('square-slider').toHavePosition(200, 0);33  });34  it("should not drag vertical slider horizontally", function() {35    helpers.initDragdealer('square-slider', {36      horizontal: false,37      vertical: true38    });39    helpers.dragTo('square-slider', 100, 0);40    expect('square-slider').toHavePosition(0, 0);41    helpers.dragTo('square-slider', 200, 200);42    expect('square-slider').toHavePosition(0, 200);43  });44  describe("should constrain handle position under the wrapper bounds", function() {45    it("when wrapper is bigger than handle", function() {46      helpers.initDragdealer('simple-slider');47      helpers.dragTo('simple-slider', -100, 0);48      expect('simple-slider').toHavePosition(0, 0);49      helpers.dragTo('simple-slider', 0, -100);50      expect('simple-slider').toHavePosition(0, 0);51      helpers.dragTo('simple-slider', 0, 100);52      expect('simple-slider').toHavePosition(0, 0);53      helpers.dragTo('simple-slider', 500, 0);54      expect('simple-slider').toHavePosition(400, 0);55    });56    it("when wrapper is bigger than handle and has padding", function() {57      helpers.initDragdealer('square-slider', {58        horizontal: true,59        vertical: true,60        top: 10,61        bottom: 20,62        left: 30,63        right: 4064      });65      helpers.dragTo('square-slider', -1000, -1000);66      expect('square-slider').toHavePosition(30, 10);67      helpers.dragTo('square-slider', 1000, -1000);68      expect('square-slider').toHavePosition(360, 10);69      helpers.dragTo('square-slider', 1000, 1000);70      expect('square-slider').toHavePosition(360, 380);71      helpers.dragTo('square-slider', -1000, 1000);72      expect('square-slider').toHavePosition(30, 380);73    });74    it("when handle is bigger than wrapper", function() {75      helpers.initDragdealer('masked-slider', {76        horizontal: true,77        vertical: true,78        top: 10,79        bottom: 10,80        left: 10,81        right: 1082      });83      helpers.dragTo('masked-slider', 1000, 1000);84      expect('masked-slider').toHavePosition(10, 10);85      helpers.dragTo('masked-slider', -1000, 1000);86      expect('masked-slider').toHavePosition(-510, 10);87      helpers.dragTo('masked-slider', -1000, -1000);88      expect('masked-slider').toHavePosition(-510, -510);89      helpers.dragTo('masked-slider', 1000, -1000);90      expect('masked-slider').toHavePosition(10, -510);91    });92  });93  it("should slide handle after releasing drag", function() {94    helpers.initDragdealer('simple-slider', {95      slide: true96    });97    helpers.dragTo('simple-slider', 50, 0);98    expect('simple-slider').toHavePosition(50, 0);99    // The slider gets a force of 4x the last movement and keeps eating a part100    // of it with every interval loop, normally we'd never move an entire 50px101    // with one mouse move102    helpers.drop('simple-slider');103    helpers.callRequestAnimationFrameMock(3000);104    expect('simple-slider').toHavePosition(250, 0);105  });106  it("should pull handle to closest step after releasing drag", function() {107    helpers.initDragdealer('simple-slider', {108      slide: false,109      // Considering the simple slider has a wrapper of 500px width and a110      // handle of 100px width, the step positions will be 0, 80, 160, 240, 320111      // and 400112      steps: 6113    });114    helpers.dragTo('simple-slider', 100, 0);115    helpers.drop('simple-slider');116    helpers.callRequestAnimationFrameMock(3000);117    expect('simple-slider').toHavePosition(80, 0);118    helpers.dragTo('simple-slider', 50, 0);119    helpers.drop('simple-slider');120    helpers.callRequestAnimationFrameMock(3000);121    expect('simple-slider').toHavePosition(80, 0);122    helpers.dragTo('simple-slider', 350, 0);123    helpers.drop('simple-slider');124    helpers.callRequestAnimationFrameMock(3000);125    expect('simple-slider').toHavePosition(320, 0);126    helpers.dragTo('simple-slider', 210, 0);127    helpers.drop('simple-slider');128    helpers.callRequestAnimationFrameMock(3000);129    expect('simple-slider').toHavePosition(240, 0);130  });131  it("should slide handle to projected step after releasing drag", function() {132    helpers.initDragdealer('simple-slider', {133      // The slider gets a force of 4x the last movement134      slide: true,135      // Considering the simple slider has a wrapper of 500px width and a136      // handle of 100px width, the step positions will be 0, 80, 160, 240, 320137      // and 400138      steps: 6139    });140    // is dragged 25px to the right, and will slide 125px, to 125, 0141    helpers.dragTo('simple-slider', 25, 0);142    helpers.drop('simple-slider');143    helpers.callRequestAnimationFrameMock(3000);144    expect('simple-slider').toHavePosition(160, 0);145    // is dragged 15px to the left, and will slide 75px, to 135, 0146    helpers.dragTo('simple-slider', 155, 0);147    helpers.drop('simple-slider');148    helpers.callRequestAnimationFrameMock(3000);149    expect('simple-slider').toHavePosition(160, 0);150    // is dragged 25px to the right, and will slide 125px, to 285, 0151    helpers.dragTo('simple-slider', 185, 0);152    helpers.drop('simple-slider');153    helpers.callRequestAnimationFrameMock(3000);154    expect('simple-slider').toHavePosition(320, 0);155    // is dragged 20px to the left, and will slide 250px, to 70, 0156    helpers.dragTo('simple-slider', 270, 0);157    helpers.drop('simple-slider');158    helpers.callRequestAnimationFrameMock(3000);159    expect('simple-slider').toHavePosition(80, 0);160  });161  it("should snap handle to closest step after releasing drag", function() {162    helpers.initDragdealer('simple-slider', {163      slide: false,164      // Considering the simple slider has a wrapper of 500px width and a165      // handle of 100px width, the step positions will be 0, 80, 160, 240, 320166      // and 400167      steps: 6,168      snap: true169    });170    helpers.dragTo('simple-slider', 100, 0);171    helpers.drop('simple-slider');172    expect('simple-slider').toHavePosition(80, 0);173    helpers.dragTo('simple-slider', 50, 0);174    helpers.drop('simple-slider');175    expect('simple-slider').toHavePosition(80, 0);176    helpers.dragTo('simple-slider', 350, 0);177    helpers.drop('simple-slider');178    expect('simple-slider').toHavePosition(320, 0);179    helpers.dragTo('simple-slider', 210, 0);180    helpers.drop('simple-slider');181    expect('simple-slider').toHavePosition(240, 0);182  });183  it("should drag loose handle outside bigger wrapper", function() {184    // Any positon offset outside the wrapper bounds will be split by 4185    helpers.initDragdealer('simple-slider', {186      loose: true187    });188    // This goes outside the wrapper with 100px, so the exceeding offset will189    // be 25px190    helpers.dragTo('simple-slider', -100, 0);191    helpers.drop('simple-slider');192    expect('simple-slider').toHavePosition(-25, 0);193    helpers.callRequestAnimationFrameMock(3000);194    expect('simple-slider').toHavePosition(0, 0);195    // This goes outside the wrapper with 200px, since 400px is the rightmost196    // position of a 100px wide handle inside a 500px wide wrapper, so the197    // exceeding offset will be 50px198    helpers.dragTo('simple-slider', 600, 0);199    helpers.drop('simple-slider');200    expect('simple-slider').toHavePosition(450, 0);201    helpers.callRequestAnimationFrameMock(3000);202    expect('simple-slider').toHavePosition(400, 0);203  });204  it("should drag loose handle inside smaller wrapper", function() {205    // Any positon offset outside the wrapper bounds will be split by 4206    helpers.initDragdealer('masked-slider', {207      horizontal: true,208      vertical: true,209      loose: true210    });211    helpers.dragTo('masked-slider', 100, 200);212    helpers.drop('masked-slider');213    expect('masked-slider').toHavePosition(25, 50);214    helpers.callRequestAnimationFrameMock(3000);215    expect('masked-slider').toHavePosition(0, 0);216    helpers.dragTo('masked-slider', -2000, -1000);217    helpers.drop('masked-slider');218    expect('masked-slider').toHavePosition(-875, -625);219    helpers.callRequestAnimationFrameMock(3000);220    expect('masked-slider').toHavePosition(-500, -500);221  });222  it("should not break dragging after repositioning", function() {223    // Fix for https://github.com/skidding/dragdealer/issues/3224    var dragdealer = helpers.initDragdealer('masked-slider', {225      horizontal: true,226      vertical: true227    });228    $('#masked-slider').css('margin-top', 200);229    helpers.dragTo('masked-slider', -250, -250);230    expect('masked-slider').toHavePosition(-250, -250);231    expect(dragdealer.getValue()).toEqual([0.5, 0.5]);232  });233  it("should not work after unbinding events", function() {234    // Spec for https://github.com/skidding/dragdealer/issues/8235    var dragdealer = helpers.initDragdealer('simple-slider');236    dragdealer.unbindEventListeners();237    helpers.dragTo('simple-slider', 200, 0);238    expect('simple-slider').toHavePosition(0, 0);239  });240  it("should stop sliding animation after unbinding events", function() {241    // Spec for https://github.com/skidding/dragdealer/issues/8242    var dragdealer = helpers.initDragdealer('simple-slider');243    helpers.dragTo('simple-slider', 200, 0);244    helpers.drop('simple-slider');245    dragdealer.unbindEventListeners();246    helpers.callRequestAnimationFrameMock(3000);247    // The handle would reach the 400, 0 position if we wouldn't unbind it248    expect('simple-slider').toHavePosition(200, 0);249  });...time-dampening.spec.js
Source:time-dampening.spec.js  
...48    const mocks = getArgsMock();49    const scroller: FluidScroller = getScroller(mocks);50    // no scroll on initial lift51    scroller.start(52      dragTo({53        selection: scrollableViewport.frame.center,54        viewport: scrollableViewport,55        state,56      }),57    );58    requestAnimationFrame.flush();59    expect(mocks.scrollWindow).not.toHaveBeenCalled();60    // would be a max scroll61    scroller.scroll(62      dragTo({63        selection: onMaxBoundary,64        viewport: scrollableViewport,65        state,66      }),67    );68    requestAnimationFrame.step();69    expect(mocks.scrollWindow).toHaveBeenCalledWith(70      patch(axis.line, config.maxPixelScroll),71    );72  });73  it('should dampen if lifted in a scrollable area', () => {74    // on start of boundary: would have been a min scroll anyway75    {76      const mocks = getArgsMock();77      const scroller: FluidScroller = getScroller(mocks);78      // lifting in scrollable area79      scroller.start(80        dragTo({81          selection: onStartBoundary,82          viewport: scrollableViewport,83          state,84        }),85      );86      requestAnimationFrame.step();87      expect(mocks.scrollWindow).toHaveBeenCalledWith(88        patch(axis.line, minScroll),89      );90    }91    // would normally be max scroll speed92    {93      const mocks = getArgsMock();94      const scroller: FluidScroller = getScroller(mocks);95      // lifting in scrollable area96      scroller.start(97        dragTo({98          selection: onMaxBoundary,99          viewport: scrollableViewport,100          state,101        }),102      );103      requestAnimationFrame.step();104      expect(mocks.scrollWindow).toHaveBeenCalledWith(105        patch(axis.line, minScroll),106      );107    }108  });109  it('should have the minimum scroll up to a small time threshold and then accelerate to the max speed as time continues', () => {110    const mocks = getArgsMock();111    const scroller: FluidScroller = getScroller(mocks);112    // starting on the max boundary which normally113    scroller.start(114      dragTo({115        selection: onMaxBoundary,116        viewport: scrollableViewport,117        state,118      }),119    );120    requestAnimationFrame.step();121    expect(mocks.scrollWindow).toHaveBeenCalledWith(122      patch(axis.line, minScroll),123    );124    mocks.scrollWindow.mockClear();125    // moving up to just before the acceleration point126    mockNow.mockReturnValueOnce(startAcceleratingAt - 1);127    scroller.scroll(128      dragTo({129        selection: onMaxBoundary,130        viewport: scrollableViewport,131        state,132      }),133    );134    // still on the min scroll135    requestAnimationFrame.step();136    expect(mocks.scrollWindow).toHaveBeenCalledWith(137      patch(axis.line, minScroll),138    );139    mocks.scrollWindow.mockClear();140    // now on the acceleration start point141    mockNow.mockReturnValueOnce(startAcceleratingAt);142    scroller.scroll(143      dragTo({144        selection: onMaxBoundary,145        viewport: scrollableViewport,146        state,147      }),148    );149    requestAnimationFrame.step();150    // still on the min scroll as the % change will be quite low151    expect(mocks.scrollWindow).toHaveBeenCalledWith(152      patch(axis.line, minScroll),153    );154    mocks.scrollWindow.mockClear();155    // Moving 30% of the way into the time dampening period156    mockNow.mockReturnValueOnce(startAcceleratingAt + accelerationRange * 0.3);157    scroller.scroll(158      dragTo({159        selection: onMaxBoundary,160        viewport: scrollableViewport,161        state,162      }),163    );164    requestAnimationFrame.step();165    const firstAcceleratedScroll: Position =166      mocks.scrollWindow.mock.calls[0][0];167    expect(firstAcceleratedScroll[axis.line]).toBeGreaterThan(minScroll);168    expect(firstAcceleratedScroll[axis.line]).toBeLessThan(169      config.maxPixelScroll,170    );171    mocks.scrollWindow.mockClear();172    // Now passing event more time (60%)173    mockNow.mockReturnValueOnce(startAcceleratingAt + accelerationRange * 0.6);174    scroller.scroll(175      dragTo({176        selection: onMaxBoundary,177        viewport: scrollableViewport,178        state,179      }),180    );181    requestAnimationFrame.step();182    const secondAcceleratedScroll: Position =183      mocks.scrollWindow.mock.calls[0][0];184    // is greater in acceleration185    expect(secondAcceleratedScroll[axis.line]).toBeGreaterThan(186      firstAcceleratedScroll[axis.line],187    );188    expect(secondAcceleratedScroll[axis.line]).toBeGreaterThan(minScroll);189    expect(secondAcceleratedScroll[axis.line]).toBeLessThan(190      config.maxPixelScroll,191    );192    mocks.scrollWindow.mockClear();193    // Moving to the end of the time dampening period194    mockNow.mockReturnValueOnce(stopAt);195    scroller.scroll(196      dragTo({197        selection: onMaxBoundary,198        viewport: scrollableViewport,199        state,200      }),201    );202    requestAnimationFrame.step();203    const lastAcceleratedScroll: Position = mocks.scrollWindow.mock.calls[0][0];204    // is greater in acceleration205    expect(lastAcceleratedScroll[axis.line]).toBeGreaterThan(206      firstAcceleratedScroll[axis.line],207    );208    expect(lastAcceleratedScroll[axis.line]).toBeGreaterThan(minScroll);209    expect(lastAcceleratedScroll[axis.line]).toEqual(config.maxPixelScroll);210  });...dnd.spec.js
Source:dnd.spec.js  
...9  beforeEach(() => {10    cy.visit('/');11  });12  it('Create Horizontal Layout', () => {13    cy.get('[data-cy="HorizontalLayout-source"]').dragTo(14      '[data-cy="nolayout-drop"]'15    );16    cy.get('[data-cy="/-drop-0"]');17  });18  it('Create Vertical Layout', () => {19    cy.get('[data-cy="VerticalLayout-source"]').dragTo(20      '[data-cy="nolayout-drop"]'21    );22    cy.get('[data-cy="/-drop-0"]');23  });24});25describe('Control Creation Dnd Tests on Example model', () => {26  beforeEach(() => {27    cy.visit('/');28    // add a layout29    cy.get('[data-cy="HorizontalLayout-source"]').dragTo(30      '[data-cy="nolayout-drop"]'31    );32  });33  it('Create "name" Control', () => {34    cy.get('[data-cy="/properties/name-source"]').dragTo(35      '[data-cy="/-drop-0"]'36    );37    // TODO more specific check38    cy.get('input');39  });40  it('Create "personalData/height" Control', () => {41    // expand personalData42    cy.get('[data-cy="/properties/personalData-source"]').click();43    // drag personalData/height44    cy.get(45      '[data-cy="/properties/personalData/properties/height-source"]'46    ).dragTo('[data-cy="/-drop-0"]');47    // TODO more specific check48    cy.get('input');49  });50});51describe('Dnd Move Tests on Example model', () => {52  beforeEach(() => {53    cy.visit('/');54    //SETUP: horizontal layout with two controls("personalData/height" and "name") and a vertical layout55    // add a layout56    cy.get('[data-cy="HorizontalLayout-source"]').dragTo(57      '[data-cy="nolayout-drop"]'58    );59    cy.get('[data-cy="/properties/personalData-source"]').click();60    cy.get(61      '[data-cy="/properties/personalData/properties/height-source"]'62    ).dragTo('[data-cy="/-drop-0"]');63    cy.get('[data-cy="/properties/name-source"]').dragTo(64      '[data-cy="/-drop-1"]'65    );66    cy.get('[data-cy="VerticalLayout-source"]').dragTo('[data-cy="/-drop-2"]');67    //check that order is: height, name68    cy.get('[data-cy="editorElement-/elements/0"]').should(69      'have.text',70      '#/properties/personalData/properties/height' + 'Height*'71    );72    cy.get('[data-cy="editorElement-/elements/1"]').should(73      'have.text',74      '#/properties/name' + 'Name'75    );76  });77  it('Move element in the same parent, to the right', () => {78    // MOVE "height" after "name"79    cy.get('[data-cy="editorElement-/elements/0-header"]').dragTo(80      '[data-cy="/-drop-2"]'81    );82    //check that order changed to: name, height83    cy.get('[data-cy="editorElement-/elements/0"]').should(84      'have.text',85      '#/properties/name' + 'Name'86    );87    cy.get('[data-cy="editorElement-/elements/1"]').should(88      'have.text',89      '#/properties/personalData/properties/height' + 'Height*'90    );91  });92  it('Move element in the same parent, to the left', () => {93    // MOVE "name" before "height"94    cy.get('[data-cy="editorElement-/elements/1-header"]').dragTo(95      '[data-cy="/-drop-0"]'96    );97    //check that order changed to: name, height98    cy.get('[data-cy="editorElement-/elements/0"]').should(99      'have.text',100      '#/properties/name' + 'Name'101    );102    cy.get('[data-cy="editorElement-/elements/1"]').should(103      'have.text',104      '#/properties/personalData/properties/height' + 'Height*'105    );106  });107  it('Move element to new parent', () => {108    // MOVE "height" to vertical layout109    cy.get('[data-cy="editorElement-/elements/0-header"]').dragTo(110      '[data-cy="/elements/2-drop-0"]'111    );112    //check that order changed to: name, vertical-layout/height113    cy.get('[data-cy="editorElement-/elements/0"]').should(114      'have.text',115      '#/properties/name' + 'Name'116    );117    cy.get('[data-cy="editorElement-/elements/1/elements/0"]').should(118      'have.text',119      '#/properties/personalData/properties/height' + 'Height*'120    );121  });122  it('No layout change when droping element in the drop point to its left', () => {123    // drop name in the drop point before it124    cy.get('[data-cy="editorElement-/elements/0-header"]').dragTo(125      '[data-cy="/-drop-0"]'126    );127    //check that order didn't change128    cy.get('[data-cy="editorElement-/elements/0"]').should(129      'have.text',130      '#/properties/personalData/properties/height' + 'Height*'131    );132    cy.get('[data-cy="editorElement-/elements/1"]').should(133      'have.text',134      '#/properties/name' + 'Name'135    );136  });137  it('No layout change when droping element in the drop point to its right', () => {138    // drop name in the drop point before it139    cy.get('[data-cy="editorElement-/elements/0-header"]').dragTo(140      '[data-cy="/-drop-1"]'141    );142    //check that order didn't change143    cy.get('[data-cy="editorElement-/elements/0"]').should(144      'have.text',145      '#/properties/personalData/properties/height' + 'Height*'146    );147    cy.get('[data-cy="editorElement-/elements/1"]').should(148      'have.text',149      '#/properties/name' + 'Name'150    );151  });152  it('Layout elements are moved with their children', () => {153    // SETUP: "height" to vertical layout154    cy.get('[data-cy="editorElement-/elements/0-header"]').dragTo(155      '[data-cy="/elements/2-drop-0"]'156    );157    //MOVE layout with control (now on position 1)158    cy.get('[data-cy="editorElement-/elements/1-header"]').dragTo(159      '[data-cy="/-drop-0"]'160    );161    //check height is contained in first element162    cy.get('[data-cy="editorElement-/elements/0/elements/0"]').should(163      'have.text',164      '#/properties/personalData/properties/height' + 'Height*'165    );166    cy.get('[data-cy="editorElement-/elements/1"]').should(167      'have.text',168      '#/properties/name' + 'Name'169    );170  });...editor.spec.js
Source:editor.spec.js  
...10    cy.visit('/');11  });12  it('Can remove control root', () => {13    // SETUP: add one control14    cy.get('[data-cy="/properties/name-source"]').dragTo(15      '[data-cy="nolayout-drop"]'16    );17    // remove control18    cy.get('[data-cy="editorElement-/-removeButton"]').click();19    // check that layout is empty20    cy.get('[data-cy="nolayout-drop"]');21  });22  it('Can remove layout root', () => {23    // SETUP: add a layout with one control24    cy.get('[data-cy="HorizontalLayout-source"]').dragTo(25      '[data-cy="nolayout-drop"]'26    );27    cy.get('[data-cy="/properties/name-source"]').dragTo(28      '[data-cy="/-drop-0"]'29    );30    // remove layuot with control31    cy.get('[data-cy="editorElement-/-removeButton"]').click();32    cy.get('[data-cy="ok-button"]').click();33    // check that layout is empty34    cy.get('[data-cy="nolayout-drop"]');35  });36  it('Can remove control', () => {37    // SETUP: add a layout with three controls38    cy.get('[data-cy="HorizontalLayout-source"]').dragTo(39      '[data-cy="nolayout-drop"]'40    );41    cy.get('[data-cy="/properties/birthDate-source"]').dragTo(42      '[data-cy="/-drop-0"]'43    );44    cy.get('[data-cy="/properties/name-source"]').dragTo(45      '[data-cy="/-drop-1"]'46    );47    cy.get('[data-cy="/properties/occupation-source"]').dragTo(48      '[data-cy="/-drop-2"]'49    );50    // remove middle control51    cy.get('[data-cy="editorElement-/elements/1-removeButton"]').click();52    // check that height and occupation controls remain53    cy.get('[data-cy="editorElement-/elements/0"]').should(54      'contain.text',55      'Birth Date'56    );57    cy.get('[data-cy="editorElement-/elements/1"]').should(58      'have.text',59      '#/properties/occupation' + 'Occupation'60    );61  });62  it('Can remove layout', () => {63    // SETUP: add a layout with three elements (two controls, one layout)64    cy.get('[data-cy="HorizontalLayout-source"]').dragTo(65      '[data-cy="nolayout-drop"]'66    );67    cy.get('[data-cy="HorizontalLayout-source"]').dragTo(68      '[data-cy="/-drop-0"]'69    );70    cy.get('[data-cy="/properties/name-source"]').dragTo(71      '[data-cy="/-drop-1"]'72    );73    cy.get('[data-cy="/properties/occupation-source"]').dragTo(74      '[data-cy="/-drop-2"]'75    );76    // remove middle control77    cy.get('[data-cy="editorElement-/elements/0-removeButton"]').click();78    // check that height and occupation controls remain79    cy.get('[data-cy="editorElement-/elements/0"]').should(80      'contain.text',81      'Name'82    );83    cy.get('[data-cy="editorElement-/elements/1"]').should(84      'have.text',85      '#/properties/occupation' + 'Occupation'86    );87  });...Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3  const browser = await chromium.launch();4  const context = await browser.newContext();5  const page = await context.newPage();6  const search = await page.$('input[name="q"]');7  await search.dragTo(search, { steps: 10 });8  await browser.close();9})();10The dragTo() method takes two arguments:11const { chromium } = require('playwright');12(async () => {13  const browser = await chromium.launch();14  const context = await browser.newContext();15  const page = await context.newPage();16  const search = await page.$('input[name="q"]');17  const searchButton = await page.$('input[name="btnK"]');18  await search.dragTo(searchButton, { steps: 10 });19  await browser.close();20})();21The dragTo() method takes two arguments:22The dragTo() method takes two arguments:Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3  const browser = await chromium.launch();4  const context = await browser.newContext();5  const page = await context.newPage();6  await page.dragTo('.navbar__inner', 100, 100);7  await page.screenshot({ path: 'drag.png' });8  await browser.close();9})();10const { chromium } = require('playwright');11(async () => {12  const browser = await chromium.launch();13  const context = await browser.newContext();14  const page = await context.newPage();15  await page.dragTo('.navbar__inner', 100, 100);16  await page.screenshot({ path: 'drag.png' });17  await browser.close();18})();19const { chromium } = require('playwright');20(async () => {21  const browser = await chromium.launch();22  const context = await browser.newContext();23  const page = await context.newPage();24  await page.dragTo('.navbar__inner', 100, 100);25  await page.screenshot({ path: 'drag.png' });26  await browser.close();27})();28const { chromium } = require('playwright');29(async () => {30  const browser = await chromium.launch();31  const context = await browser.newContext();32  const page = await context.newPage();33  await page.dragTo('.navbar__inner', 100, 100);34  await page.screenshot({ path: 'drag.png' });35  await browser.close();36})();37const { chromium } = require('playwright');38(async () => {39  const browser = await chromium.launch();40  const context = await browser.newContext();41  const page = await context.newPage();42  await page.dragTo('.navbar__inner', 100, 100);43  await page.screenshot({ path: 'dragUsing AI Code Generation
1const { chromium } = require('playwright');2(async () => {3    const browser = await chromium.launch({ headless: false });4    const context = await browser.newContext();5    const page = await context.newPage();6    await page.waitForSelector('iframe[name="result"]');7    const frame = page.frames().find(f => f.name() === 'result');8    await frame.waitForSelector('canvas');9    const canvas = await frame.$('canvas');10    const boundingBox = await canvas.boundingBox();11    const x = boundingBox.x + boundingBox.width / 2;12    const y = boundingBox.y + boundingBox.height / 2;13    await page.mouse.move(x, y);14    await page.mouse.down();15    await page.mouse.move(x + 100, y + 100, { steps: 10 });16    await page.mouse.up();17    await page.screenshot({ path: `example.png` });18    await browser.close();19})();Using AI Code Generation
1const { chromium } = require('playwright');2const { dragTo } = require('playwright/lib/input');3(async () => {4  const browser = await chromium.launch();5  const page = await browser.newPage();6  await page.waitForSelector('#iframeResult');7  const frame = await page.frame({8  });9  await frame.waitForSelector('#drag1');10  const drag = await frame.$('#drag1');11  const drop = await frame.$('#div2');12  await dragTo(drag, drop);13  await page.close();14})();15const { helper } = require('./helper');16module.exports = {17   * @param {!ElementHandle} source18   * @param {!ElementHandle} target19   * @param {{steps?: number}=} options20  async dragTo(source, target, options = {}) {21    const { steps = 5 } = options;22    const sourceBox = await source.boundingBox();23    const targetBox = await target.boundingBox();24    if (!sourceBox || !targetBox)25      throw new Error('Both source and target must be visible');26    const x = Math.round(sourceBox.x + sourceBox.width / 2);27    const y = Math.round(sourceBox.y + sourceBox.height / 2);28    const destinationX = Math.round(targetBox.x + targetBox.width / 2);29    const destinationY = Math.round(targetBox.y + targetBox.height / 2);30    await source._page.mouse.move(x, y);31    await source._page.mouse.down();32    for (let i = 1; i <= steps; i++) {33      await source._page.mouse.move(34          x + Math.round((i * (destinationX - x)) / steps),35          y + Math.round((i * (destinationY - y)) / steps),36          { steps: 1 }37      );38    }39    await source._page.mouse.up();40  },41};42const dragAndDrop = async (source, target) => {43  const dataTransfer = new DataTransfer();44  dataTransfer.setData('text', '');Using AI Code Generation
1const { dragTo } = require('playwright/lib/input');2const { chromium } = require('playwright');3(async () => {4    const browser = await chromium.launch();5    const context = await browser.newContext();6    const page = await context.newPage();7    await page.waitForSelector('#iframeResult');8    const frame = await page.frame({ name: 'iframeResult' });9    const source = await frame.$('#drag1');10    const target = await frame.$('#div2');11    await dragTo(source, target);12    await browser.close();13})();14module.exports.dragTo = async function (source, target) {15    const page = source._page;16    await page._delegate.input.dragTo(source, target);17};18class Page {19    async dragTo(source, target) {20        const { x: sourceX, y: sourceY } = await source._clientBoundingRect();21        const { x: targetX, y: targetY } = await target._clientBoundingRect();22        await this._page._delegate.input.dispatchMouseEvent({23        });24        await this._page._delegate.input.dispatchMouseEvent({25        });26        await this._page._delegate.input.dispatchMouseEvent({27        });28    }29}30class CRPage {31    async dispatchMouseEvent(params) {32        await this._mainFrameSession._send('Input.dispatchMouseEvent', params);33    }34}35class CRSession {36    async _send(method, params) {37        const id = ++this._lastId;Using AI Code Generation
1const {chromium} = require('playwright');2(async () => {3  const browser = await chromium.launch();4  const page = await browser.newPage();5  await page.setViewportSize({ width: 1920, height: 1080 });6  await page.waitForSelector('#tryhome > iframe');7  await frame.waitForSelector('#draggable');8  await frame.waitForSelector('#droptarget');9  await frame.dragTo('#draggable', '#droptarget');10  await browser.close();11})();12const {chromium} = require('playwright');13(async () => {14  const browser = await chromium.launch();15  const page = await browser.newPage();16  await page.setViewportSize({ width: 1920, height: 1080 });17  await page.waitForSelector('#tryhome > iframe');18  await frame.waitForSelector('#draggable');19  await frame.waitForSelector('#droptarget');20  await frame.dragTo('#draggable', '#droptarget');21  await browser.close();22})();23const {chromium} = require('playwright');24(async () => {25  const browser = await chromium.launch();26  const page = await browser.newPage();27  await page.setViewportSize({ width: 1920, height: 1080 });28  await page.waitForSelector('#tryhome > iframe');Using AI Code Generation
1const { dragTo } = require('playwright/lib/server/frames');2const { chromium } = require('playwright');3(async () => {4  const browser = await chromium.launch();5  const context = await browser.newContext();6  const page = await context.newPage();7  const sliderHandle = await page.$('.slider-handle');8  await dragTo(page, sliderHandle, { x: -100, y: 0 });9  await dragTo(page, sliderHandle, { x: 100, y: 0 });10  await browser.close();11})();Using AI Code Generation
1const { dragTo } = require('@playwright/test/lib/internal/autotools');2const { chromium, devices } = require('playwright');3(async () => {4  const browser = await chromium.launch();5  const context = await browser.newContext({6    geolocation: { latitude: 59.95, longitude: 30.31667 },7  });8  const page = await context.newPage();9  await page.click('text="Get started"');10  await dragTo(page, 'css=button:has-text("Drag me")', { x: 0, y: 200 });11  await page.screenshot({ path: `drag.png` });12  await browser.close();13})();14import { PlaywrightTestConfig } from '@playwright/test';15const config: PlaywrightTestConfig = {16    {17      use: { browserName: 'chromium' },18    },19  use: {20    viewport: { width: 1280, height: 720 },21  },22};23export default config;24{25  "scripts": {26  },27  "dependencies": {28  }29}Using AI Code Generation
1const {chromium} = require('playwright');2(async () => {3    const browser = await chromium.launch();4    const context = await browser.newContext();5    const page = await context.newPage();6    await page.waitForTimeout(5000);7    await page.click('#accept-choices');8    await page.waitForTimeout(5000);9    const frame = page.frame({name: 'iframeResult'});10    await frame.waitForSelector('#div1');11    const element = await frame.$('#div1');12    await element.dragTo(100, 100);13    await page.waitForTimeout(5000);14    await browser.close();15})();Using AI Code Generation
1const { dragTo } = require('@playwright/test/lib/autotools');2const { dragTo } = require('@playwright/test/lib/autotools');3The dragTo() method is used to drag an element to a specified offset. It takes two parameters:4const { dragTo } = require('@playwright/test/lib/autotools');5const handle = page.locator('div');6await dragTo(handle, { offsetX: 100, offsetY: 100 });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!!
