1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import {
    
  11.   clampState,
    
  12.   moveStateToRange,
    
  13.   areScrollStatesEqual,
    
  14.   translateState,
    
  15.   zoomState,
    
  16. } from '../scrollState';
    
  17. 
    
  18. describe(clampState, () => {
    
  19.   it('should passthrough offset if state fits within container', () => {
    
  20.     expect(
    
  21.       clampState({
    
  22.         state: {offset: 0, length: 50},
    
  23.         minContentLength: 0,
    
  24.         maxContentLength: 100,
    
  25.         containerLength: 50,
    
  26.       }).offset,
    
  27.     ).toBeCloseTo(0, 10);
    
  28.     expect(
    
  29.       clampState({
    
  30.         state: {offset: -20, length: 100},
    
  31.         minContentLength: 0,
    
  32.         maxContentLength: 100,
    
  33.         containerLength: 50,
    
  34.       }).offset,
    
  35.     ).toBeCloseTo(-20, 10);
    
  36.   });
    
  37. 
    
  38.   it('should clamp offset if offset causes content to go out of container', () => {
    
  39.     expect(
    
  40.       clampState({
    
  41.         state: {offset: -1, length: 50},
    
  42.         minContentLength: 0,
    
  43.         maxContentLength: 100,
    
  44.         containerLength: 50,
    
  45.       }).offset,
    
  46.     ).toBeCloseTo(0, 10);
    
  47.     expect(
    
  48.       clampState({
    
  49.         state: {offset: 1, length: 50},
    
  50.         minContentLength: 0,
    
  51.         maxContentLength: 100,
    
  52.         containerLength: 50,
    
  53.       }).offset,
    
  54.     ).toBeCloseTo(0, 10);
    
  55. 
    
  56.     expect(
    
  57.       clampState({
    
  58.         state: {offset: -51, length: 100},
    
  59.         minContentLength: 0,
    
  60.         maxContentLength: 100,
    
  61.         containerLength: 50,
    
  62.       }).offset,
    
  63.     ).toBeCloseTo(-50, 10);
    
  64.     expect(
    
  65.       clampState({
    
  66.         state: {offset: 1, length: 100},
    
  67.         minContentLength: 0,
    
  68.         maxContentLength: 100,
    
  69.         containerLength: 50,
    
  70.       }).offset,
    
  71.     ).toBeCloseTo(0, 10);
    
  72.   });
    
  73. 
    
  74.   it('should passthrough length if container fits in content', () => {
    
  75.     expect(
    
  76.       clampState({
    
  77.         state: {offset: 0, length: 70},
    
  78.         minContentLength: 0,
    
  79.         maxContentLength: 100,
    
  80.         containerLength: 50,
    
  81.       }).length,
    
  82.     ).toBeCloseTo(70, 10);
    
  83.     expect(
    
  84.       clampState({
    
  85.         state: {offset: 0, length: 50},
    
  86.         minContentLength: 0,
    
  87.         maxContentLength: 100,
    
  88.         containerLength: 50,
    
  89.       }).length,
    
  90.     ).toBeCloseTo(50, 10);
    
  91.     expect(
    
  92.       clampState({
    
  93.         state: {offset: 0, length: 100},
    
  94.         minContentLength: 0,
    
  95.         maxContentLength: 100,
    
  96.         containerLength: 50,
    
  97.       }).length,
    
  98.     ).toBeCloseTo(100, 10);
    
  99.   });
    
  100. 
    
  101.   it('should clamp length to minimum of max(minContentLength, containerLength)', () => {
    
  102.     expect(
    
  103.       clampState({
    
  104.         state: {offset: -20, length: 0},
    
  105.         minContentLength: 20,
    
  106.         maxContentLength: 100,
    
  107.         containerLength: 50,
    
  108.       }).length,
    
  109.     ).toBeCloseTo(50, 10);
    
  110.     expect(
    
  111.       clampState({
    
  112.         state: {offset: -20, length: 0},
    
  113.         minContentLength: 50,
    
  114.         maxContentLength: 100,
    
  115.         containerLength: 20,
    
  116.       }).length,
    
  117.     ).toBeCloseTo(50, 10);
    
  118.   });
    
  119. 
    
  120.   it('should clamp length to maximum of max(containerLength, maxContentLength)', () => {
    
  121.     expect(
    
  122.       clampState({
    
  123.         state: {offset: -20, length: 100},
    
  124.         minContentLength: 0,
    
  125.         maxContentLength: 40,
    
  126.         containerLength: 50,
    
  127.       }).length,
    
  128.     ).toBeCloseTo(50, 10);
    
  129.     expect(
    
  130.       clampState({
    
  131.         state: {offset: -20, length: 100},
    
  132.         minContentLength: 0,
    
  133.         maxContentLength: 50,
    
  134.         containerLength: 40,
    
  135.       }).length,
    
  136.     ).toBeCloseTo(50, 10);
    
  137.   });
    
  138. });
    
  139. 
    
  140. describe(translateState, () => {
    
  141.   it('should translate state by delta and leave length unchanged', () => {
    
  142.     expect(
    
  143.       translateState({
    
  144.         state: {offset: 0, length: 100},
    
  145.         delta: -3.14,
    
  146.         containerLength: 50,
    
  147.       }),
    
  148.     ).toEqual({offset: -3.14, length: 100});
    
  149.   });
    
  150. 
    
  151.   it('should clamp resulting offset', () => {
    
  152.     expect(
    
  153.       translateState({
    
  154.         state: {offset: 0, length: 50},
    
  155.         delta: -3.14,
    
  156.         containerLength: 50,
    
  157.       }).offset,
    
  158.     ).toBeCloseTo(0, 10);
    
  159.     expect(
    
  160.       translateState({
    
  161.         state: {offset: 0, length: 53},
    
  162.         delta: -100,
    
  163.         containerLength: 50,
    
  164.       }).offset,
    
  165.     ).toBeCloseTo(-3, 10);
    
  166.   });
    
  167. });
    
  168. 
    
  169. describe(zoomState, () => {
    
  170.   it('should scale width by multiplier', () => {
    
  171.     expect(
    
  172.       zoomState({
    
  173.         state: {offset: 0, length: 100},
    
  174.         multiplier: 1.5,
    
  175.         fixedPoint: 0,
    
  176. 
    
  177.         minContentLength: 0,
    
  178.         maxContentLength: 1000,
    
  179.         containerLength: 50,
    
  180.       }),
    
  181.     ).toEqual({offset: 0, length: 150});
    
  182.   });
    
  183. 
    
  184.   it('should clamp zoomed state', () => {
    
  185.     const zoomedState = zoomState({
    
  186.       state: {offset: -20, length: 100},
    
  187.       multiplier: 0.1,
    
  188.       fixedPoint: 5,
    
  189. 
    
  190.       minContentLength: 50,
    
  191.       maxContentLength: 100,
    
  192.       containerLength: 50,
    
  193.     });
    
  194.     expect(zoomedState.offset).toBeCloseTo(0, 10);
    
  195.     expect(zoomedState.length).toBeCloseTo(50, 10);
    
  196.   });
    
  197. 
    
  198.   it('should maintain containerStart<->fixedPoint distance', () => {
    
  199.     const offset = -20;
    
  200.     const fixedPointFromContainer = 10;
    
  201. 
    
  202.     const zoomedState = zoomState({
    
  203.       state: {offset, length: 100},
    
  204.       multiplier: 2,
    
  205.       fixedPoint: fixedPointFromContainer - offset,
    
  206. 
    
  207.       minContentLength: 0,
    
  208.       maxContentLength: 1000,
    
  209.       containerLength: 50,
    
  210.     });
    
  211. 
    
  212.     expect(zoomedState).toMatchInlineSnapshot(`
    
  213.       {
    
  214.         "length": 200,
    
  215.         "offset": -50,
    
  216.       }
    
  217.     `);
    
  218.   });
    
  219. });
    
  220. 
    
  221. describe(moveStateToRange, () => {
    
  222.   it('should set [rangeStart, rangeEnd] = container', () => {
    
  223.     const movedState = moveStateToRange({
    
  224.       state: {offset: -20, length: 100},
    
  225.       rangeStart: 50,
    
  226.       rangeEnd: 100,
    
  227.       contentLength: 400,
    
  228. 
    
  229.       minContentLength: 10,
    
  230.       maxContentLength: 1000,
    
  231.       containerLength: 50,
    
  232.     });
    
  233. 
    
  234.     expect(movedState).toMatchInlineSnapshot(`
    
  235.       {
    
  236.         "length": 400,
    
  237.         "offset": -50,
    
  238.       }
    
  239.     `);
    
  240.   });
    
  241. });
    
  242. 
    
  243. describe(areScrollStatesEqual, () => {
    
  244.   it('should return true if equal', () => {
    
  245.     expect(
    
  246.       areScrollStatesEqual({offset: 0, length: 0}, {offset: 0, length: 0}),
    
  247.     ).toBe(true);
    
  248.     expect(
    
  249.       areScrollStatesEqual({offset: -1, length: 1}, {offset: -1, length: 1}),
    
  250.     ).toBe(true);
    
  251.   });
    
  252. 
    
  253.   it('should return false if not equal', () => {
    
  254.     expect(
    
  255.       areScrollStatesEqual({offset: 0, length: 0}, {offset: -1, length: 0}),
    
  256.     ).toBe(false);
    
  257.     expect(
    
  258.       areScrollStatesEqual({offset: -1, length: 1}, {offset: -1, length: 0}),
    
  259.     ).toBe(false);
    
  260.   });
    
  261. });