chromium/chrome/test/data/webui/lens/overlay/post_selection_renderer_test.ts

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'chrome-untrusted://lens/post_selection_renderer.js';

import {BrowserProxyImpl} from 'chrome-untrusted://lens/browser_proxy.js';
import type {LensPageRemote} from 'chrome-untrusted://lens/lens.mojom-webui.js';
import {UserAction} from 'chrome-untrusted://lens/lens.mojom-webui.js';
import type {PostSelectionBoundingBox, PostSelectionRendererElement} from 'chrome-untrusted://lens/post_selection_renderer.js';
import {CUTOUT_RADIUS_PX, MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, MIN_BOX_SIZE_PX, PERIMETER_SELECTION_PADDING_PX} from 'chrome-untrusted://lens/post_selection_renderer.js';
import type {GestureEvent} from 'chrome-untrusted://lens/selection_utils.js';
import {GestureState} from 'chrome-untrusted://lens/selection_utils.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js';
import type {MetricsTracker} from 'chrome-untrusted://webui-test/metrics_test_support.js';
import {fakeMetricsPrivate} from 'chrome-untrusted://webui-test/metrics_test_support.js';
import {waitAfterNextRender} from 'chrome-untrusted://webui-test/polymer_test_util.js';
import {isVisible} from 'chrome-untrusted://webui-test/test_util.js';

import {assertPixelsWithinThreshold, assertWithinThreshold} from '../utils/object_utils.js';

import {TestLensOverlayBrowserProxy} from './test_overlay_browser_proxy.js';

const TEST_WIDTH = 800;
const TEST_HEIGHT = 500;

function normalizeX(x: number): number {
  return x / TEST_WIDTH;
}

function normalizeY(y: number): number {
  return y / TEST_HEIGHT;
}

suite('PostSelectionRenderer', () => {
  let postSelectionRenderer: PostSelectionRendererElement;
  let testBrowserProxy: TestLensOverlayBrowserProxy;
  let callbackRouterRemote: LensPageRemote;
  let metrics: MetricsTracker;

  setup(() => {
    // Resetting the HTML needs to be the first thing we do in setup to
    // guarantee that any singleton instances don't change while any UI is still
    // attached to the DOM.
    document.body.innerHTML = window.trustedTypes!.emptyHTML;

    testBrowserProxy = new TestLensOverlayBrowserProxy();
    BrowserProxyImpl.setInstance(testBrowserProxy);
    callbackRouterRemote =
        testBrowserProxy.callbackRouter.$.bindNewPipeAndPassRemote();

    postSelectionRenderer = document.createElement('post-selection-renderer');
    postSelectionRenderer.setSelectionOverlayRectForTesting(
        new DOMRect(0, 0, TEST_WIDTH, TEST_HEIGHT));

    postSelectionRenderer.style.display = 'block';
    postSelectionRenderer.style.width = `${TEST_WIDTH}px`;
    postSelectionRenderer.style.height = `${TEST_HEIGHT}px`;
    metrics = fakeMetricsPrivate();

    document.body.appendChild(postSelectionRenderer);
    return waitAfterNextRender(postSelectionRenderer);
  });

  async function triggerPostSelectionRender(
      boundingBox: PostSelectionBoundingBox): Promise<void> {
    document.dispatchEvent(
        new CustomEvent('render-post-selection', {detail: boundingBox}));
    return waitAfterNextRender(postSelectionRenderer);
  }

  // Drags on a corner by xOffset horizontal pixels and yOffset vertical pixels.
  // The corner to drag on is determined by the top and left variables. Ex. top:
  // false and left: true would click on the bottom left corner.
  function simulateCornerDrag(
      top: boolean, left: boolean, xOffset: number, yOffset: number): void {
    const postSelectionBoundingBox =
        postSelectionRenderer.$.postSelection.getBoundingClientRect();
    const xTarget =
        left ? postSelectionBoundingBox.left : postSelectionBoundingBox.right;
    const yTarget =
        top ? postSelectionBoundingBox.top : postSelectionBoundingBox.bottom;
    simulateDrag(xTarget, yTarget, xOffset, yOffset);
  }

  function simulateDrag(
      xStart: number, yStart: number, xOffset: number, yOffset: number): void {
    const dragGesture: GestureEvent = {
      state: GestureState.DRAGGING,
      startX: xStart,
      startY: yStart,
      clientX: xStart,
      clientY: yStart,
    };

    assertTrue(postSelectionRenderer.handleDownGesture(dragGesture));
    dragGesture.clientX = xStart + xOffset;
    dragGesture.clientY = yStart + yOffset;

    postSelectionRenderer.handleDragGesture(dragGesture);
    postSelectionRenderer.handleUpGesture();
  }

  // Verifies the post seleciton is rendered with the given percentage values
  // between 0-1.
  function assertPostSelectionRender(
      expectedLeft: number, expectedTop: number, expectedWidth: number,
      expectedHeight: number): void {
    assertWithinThreshold(
        expectedLeft * 100,
        parseFloat(
            postSelectionRenderer.style.getPropertyValue('--selection-left')));
    assertWithinThreshold(
        expectedTop * 100,
        parseFloat(
            postSelectionRenderer.style.getPropertyValue('--selection-top')));
    assertWithinThreshold(
        expectedWidth * 100,
        parseFloat(
            postSelectionRenderer.style.getPropertyValue('--selection-width')));
    assertWithinThreshold(
        expectedHeight * 100,
        parseFloat(postSelectionRenderer.style.getPropertyValue(
            '--selection-height')));
  }

  // Verifies the selection corners are rendered with the given pixel values.
  function assertPostSelectionRenderCorners(
      expectedCornerLength: number, expectedCornerRadius: number,
      expectedCutoutRadius: number): void {
    assertPixelsWithinThreshold(
        `${expectedCornerLength}px`,

        postSelectionRenderer.style.getPropertyValue(
            '--post-selection-corner-horizontal-length'));
    assertPixelsWithinThreshold(
        `${expectedCornerLength}px`,

        postSelectionRenderer.style.getPropertyValue(
            '--post-selection-corner-vertical-length'));
    assertPixelsWithinThreshold(
        `${expectedCornerRadius}px`,

        postSelectionRenderer.style.getPropertyValue(
            '--post-selection-corner-radius'));
    assertPixelsWithinThreshold(
        `${expectedCutoutRadius}px`,
        postSelectionRenderer.style.getPropertyValue(
            '--post-selection-cutout-corner-radius'));
  }

  // Verifies that a Lens request was issued with the given percentage values
  // between 0-1.
  async function assertLensRegionRequest(
      expectedLeft: number, expectedTop: number, expectedWidth: number,
      expectedHeight: number): Promise<void> {
    await testBrowserProxy.handler.whenCalled('issueLensRegionRequest');
    const rect =
        testBrowserProxy.handler.getArgs('issueLensRegionRequest')[0][0];
    assertWithinThreshold(expectedLeft + expectedWidth / 2, rect.box.x);
    assertWithinThreshold(expectedTop + expectedHeight / 2, rect.box.y);
    assertWithinThreshold(expectedWidth, rect.box.width);
    assertWithinThreshold(expectedHeight, rect.box.height);
  }

  test('PostSelectionUnhides', async () => {
    // Verifies the post selection bounding box unhides after receiving
    // `render-post-selection` event.
    await triggerPostSelectionRender(
        {top: 0, left: 0, width: 0.2, height: 0.2});

    assertTrue(isVisible(postSelectionRenderer.$.postSelection));
  });

  test('PostSelectionRendersCorrectly', async () => {
    // Verifies the post selection bounding box renders correctly after
    // receiving `render-post-selection` event.
    const postSelectionBox = {top: 0.2, left: 0.35, width: 0.5, height: 0.3};
    await triggerPostSelectionRender(postSelectionBox);

    const renderedSelectionBox =
        postSelectionRenderer.$.postSelection.getBoundingClientRect();

    assertEquals(TEST_HEIGHT * postSelectionBox.top, renderedSelectionBox.top);
    assertEquals(TEST_WIDTH * postSelectionBox.left, renderedSelectionBox.left);
    assertEquals(
        TEST_HEIGHT * postSelectionBox.height, renderedSelectionBox.height);
    assertEquals(
        TEST_WIDTH * postSelectionBox.width, renderedSelectionBox.width);
  });

  test('PostSelectionHides', async () => {
    // Verifies the post selection bounding box hides after receiving
    // `render-post-selection` event with invalid dimensions.
    await triggerPostSelectionRender(
        {top: 0, left: 100, height: -1, width: 50});

    assertFalse(isVisible(postSelectionRenderer.$.postSelection));
  });

  test('PostSelectionClearSelection', async () => {
    // Verifies the post selection bounding box hides after clearSelection() is
    // called.
    await triggerPostSelectionRender(
        {top: 0, left: 0, width: 0.2, height: 0.2});
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    postSelectionRenderer.clearSelection();
    await waitAfterNextRender(postSelectionRenderer);
    assertFalse(isVisible(postSelectionRenderer.$.postSelection));
  });

  test('PostSelectionTopLeft', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ true, /*left=*/ true, /*xOffset=*/ 20, /*yOffset=*/ 20);

    const expectedLeft = normalizeX(30);
    const expectedTop = normalizeY(30);
    const expectedWidth = normalizeX(80);
    const expectedHeight = normalizeY(50);

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, CUTOUT_RADIUS_PX);
    assertEquals(1, metrics.count('Lens.Overlay.Overlay.UserAction'));
    assertEquals(
        1,
        metrics.count(
            'Lens.Overlay.Overlay.UserAction',
            UserAction.kRegionSelectionChange));
    assertEquals(
        1,
        metrics.count(
            'Lens.Overlay.Overlay.ByInvocationSource.AppMenu.UserAction',
            UserAction.kRegionSelectionChange));
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionTopLeftMIN_BOX_SIZE', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ true, /*left=*/ true, /*xOffset=*/ 200, /*yOffset=*/ 200);

    const expectedLeft = normalizeX(110 - MIN_BOX_SIZE_PX);
    const expectedTop = normalizeY(80 - MIN_BOX_SIZE_PX);
    const expectedWidth = normalizeX(MIN_BOX_SIZE_PX);
    const expectedHeight = normalizeY(MIN_BOX_SIZE_PX);
    const expectedCornerLength = MIN_BOX_SIZE_PX / 2;
    const expectedCornerRadius = MIN_BOX_SIZE_PX / 3;
    const expectedCutoutRadius = 0;

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        expectedCornerLength, expectedCornerRadius, expectedCutoutRadius);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionTopLeftIntermediateBox', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ true, /*left=*/ true, /*xOffset=*/ 40, /*yOffset=*/ 40);

    const expectedLeft = normalizeX(50);
    const expectedTop = normalizeY(50);
    const expectedWidth = normalizeX(60);
    const expectedHeight = normalizeY(30);
    const expectedCornerLength = 15;
    const expectedCornerRadius = 10;
    const expectedCutoutRadius = 0;

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        expectedCornerLength, expectedCornerRadius, expectedCutoutRadius);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionTopLeftOutOfBounds', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ true, /*left=*/ true, /*xOffset=*/ -50, /*yOffset=*/ -50);

    const expectedLeft = normalizeX(PERIMETER_SELECTION_PADDING_PX);
    const expectedTop = normalizeY(PERIMETER_SELECTION_PADDING_PX);
    const expectedWidth = normalizeX(100 + 10 - PERIMETER_SELECTION_PADDING_PX);
    const expectedHeight = normalizeY(70 + 10 - PERIMETER_SELECTION_PADDING_PX);

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, CUTOUT_RADIUS_PX);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionTopRight', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ true, /*left=*/ false, /*xOffset=*/ 20, /*yOffset=*/ 20);

    const expectedLeft = normalizeX(10);
    const expectedTop = normalizeY(30);
    const expectedWidth = normalizeX(120);
    const expectedHeight = normalizeY(50);

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, CUTOUT_RADIUS_PX);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionTopRightMIN_BOX_SIZE', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ true, /*left=*/ false, /*xOffset=*/ -200, /*yOffset=*/ 200);

    const expectedLeft = normalizeX(10);
    const expectedTop = normalizeY(80 - MIN_BOX_SIZE_PX);
    const expectedWidth = normalizeX(MIN_BOX_SIZE_PX);
    const expectedHeight = normalizeY(MIN_BOX_SIZE_PX);
    const expectedCornerLength = MIN_BOX_SIZE_PX / 2;
    const expectedCornerRadius = MIN_BOX_SIZE_PX / 3;
    const expectedCutoutRadius = 0;

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        expectedCornerLength, expectedCornerRadius, expectedCutoutRadius);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionTopRightOutOfBounds', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ true, /*left=*/ false, /*xOffset=*/ TEST_WIDTH,
        /*yOffset=*/ -50);

    const expectedLeft = normalizeX(10);
    const expectedTop = normalizeY(PERIMETER_SELECTION_PADDING_PX);
    const expectedWidth =
        normalizeX(TEST_WIDTH - 10 - PERIMETER_SELECTION_PADDING_PX);
    const expectedHeight = normalizeY(70 + 10 - PERIMETER_SELECTION_PADDING_PX);

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, CUTOUT_RADIUS_PX);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionBottomRight', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ false, /*left=*/ false, /*xOffset=*/ 20, /*yOffset=*/ 20);

    const expectedLeft = normalizeX(10);
    const expectedTop = normalizeY(10);
    const expectedWidth = normalizeX(120);
    const expectedHeight = normalizeY(90);

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, CUTOUT_RADIUS_PX);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionBottomRightMIN_BOX_SIZE', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ false, /*left=*/ false, /*xOffset=*/ -200, /*yOffset=*/ -200);

    const expectedLeft = normalizeX(10);
    const expectedTop = normalizeY(10);
    const expectedWidth = normalizeX(MIN_BOX_SIZE_PX);
    const expectedHeight = normalizeY(MIN_BOX_SIZE_PX);
    const expectedCornerLength = MIN_BOX_SIZE_PX / 2;
    const expectedCornerRadius = MIN_BOX_SIZE_PX / 3;
    const expectedCutoutRadius = 0;

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        expectedCornerLength, expectedCornerRadius, expectedCutoutRadius);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionBottomRightOutOfBounds', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ false, /*left=*/ false, /*xOffset=*/ TEST_WIDTH,
        /*yOffset=*/ TEST_HEIGHT);

    const expectedLeft = normalizeX(10);
    const expectedTop = normalizeY(10);
    const expectedWidth =
        normalizeX(TEST_WIDTH - 10 - PERIMETER_SELECTION_PADDING_PX);
    const expectedHeight =
        normalizeY(TEST_HEIGHT - 10 - PERIMETER_SELECTION_PADDING_PX);

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, CUTOUT_RADIUS_PX);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionBottomLeft', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ false, /*left=*/ true, /*xOffset=*/ 20, /*yOffset=*/ 20);

    const expectedLeft = normalizeX(30);
    const expectedTop = normalizeY(10);
    const expectedWidth = normalizeX(80);
    const expectedHeight = normalizeY(90);

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, CUTOUT_RADIUS_PX);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionBottomLeftMIN_BOX_SIZE', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ false, /*left=*/ true, /*xOffset=*/ 200, /*yOffset=*/ -200);

    const expectedLeft = normalizeX(110 - MIN_BOX_SIZE_PX);
    const expectedTop = normalizeY(10);
    const expectedWidth = normalizeX(MIN_BOX_SIZE_PX);
    const expectedHeight = normalizeY(MIN_BOX_SIZE_PX);
    const expectedCornerLength = MIN_BOX_SIZE_PX / 2;
    const expectedCornerRadius = MIN_BOX_SIZE_PX / 3;
    const expectedCutoutRadius = 0;

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        expectedCornerLength, expectedCornerRadius, expectedCutoutRadius);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionBottomLeftOutOfBounds', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    await simulateCornerDrag(
        /*top=*/ false, /*left=*/ true, /*xOffset=*/ -50,
        /*yOffset=*/ TEST_HEIGHT);

    const expectedLeft = normalizeX(PERIMETER_SELECTION_PADDING_PX);
    const expectedTop = normalizeY(10);
    const expectedWidth = normalizeX(100 + 10 - PERIMETER_SELECTION_PADDING_PX);
    const expectedHeight =
        normalizeY(TEST_HEIGHT - 10 - PERIMETER_SELECTION_PADDING_PX);

    assertPostSelectionRender(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
    assertPostSelectionRenderCorners(
        MAX_CORNER_LENGTH_PX, MAX_CORNER_RADIUS_PX, CUTOUT_RADIUS_PX);
    await assertLensRegionRequest(
        expectedLeft, expectedTop, expectedWidth, expectedHeight);
  });

  test('PostSelectionDraggingDisabled', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    const dragGesture: GestureEvent = {
      state: GestureState.DRAGGING,
      startX: 60,
      startY: 45,
      clientX: 60,
      clientY: 45,
    };

    assertFalse(postSelectionRenderer.handleDownGesture(dragGesture));
  });

  test('PostSelectionClearAllSelectionsCallback', async () => {
    await triggerPostSelectionRender({
      top: normalizeY(10),
      left: normalizeX(10),
      width: normalizeX(100),
      height: normalizeY(70),
    });
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));

    callbackRouterRemote.clearAllSelections();
    await waitAfterNextRender(postSelectionRenderer);
    assertFalse(isVisible(postSelectionRenderer.$.postSelection));
  });


  test('PostSelectionSetPostRegionSelectionCallback', async () => {
    assertFalse(isVisible(postSelectionRenderer.$.postSelection));

    callbackRouterRemote.setPostRegionSelection({
      box: {
        x: normalizeX(10),
        y: normalizeY(10),
        width: normalizeX(100),
        height: normalizeY(70),
      },
      rotation: 0.0,
      coordinateType: 1,
    });
    await waitAfterNextRender(postSelectionRenderer);
    assertTrue(isVisible(postSelectionRenderer.$.postSelection));
  });
});