wpt / css / css-overflow / scroll-axis-lock.html

Status: FAIL | Duration: 66ms | Subtests: 0/2 | Open test on wpt.live | wpt.fyi

Data from commit:
a50cb89 wpt: run reference-named files which are themselves tests (#836) (2026-09-03)

SubtestStatusMessage
scroll-axis-lock: none allows free diagonal touch scroll even with steep angle (no railing)FAILpromise_test: Unhandled rejection with value: object "TypeError: not a callable function"
scroll-axis-lock: none allows free diagonal wheel scroll even with steep angle (no railing)FAILpromise_test: Unhandled rejection with value: object "TypeError: not a callable function"

/css/css-overflow/scroll-axis-lock.html

<!DOCTYPE html>
<title>CSS Scroll Snap: scroll-axis-lock</title>
<link rel="help"
      href="https://drafts.csswg.org/css-scroll-snap-2/#scroll-axis-lock">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/dom/events/scrolling/scroll_support.js"></script>
<style>
#scroller {
  margin-left: 200px;
  margin-top: 100px;
  width: 200px;
  height: 200px;
  overflow: scroll;
  border: 1px solid black;
  scroll-axis-lock: none;
}
#content {
  width: 1000px;
  height: 1000px;
  background: linear-gradient(45deg, white, black);
}
</style>

<div id="scroller">
  <div id="content"></div>
</div>

<script>
async function run_test(t, input_source) {
  await waitForCompositorReady();

  const scroller = document.getElementById('scroller');
  await waitForScrollReset(t, scroller);
  assert_equals(scroller.scrollLeft, 0);
  assert_equals(scroller.scrollTop, 0);

  let received_wheel_event = null;

  // Scroll mostly vertically, with a small horizontal component.
  // Move left (scroll right) by 2, up (scroll down) by 150.
  // This steep angle would normally trigger vertical railing
  // (horizontal scroll = 0).
  // With scroll-axis-lock: none, it should not rail.
  const bounds = scroller.getBoundingClientRect();
  const start_x = bounds.left + bounds.width / 2;
  const start_y = bounds.top + bounds.height / 2;
  const delta_x = 2;
  const delta_y = 150;

  // We use tolerances because the final scroll offsets might not
  // match the input deltas exactly. For touch, the initial gesture movement is
  // affected by touch slop (which is platform-dependent), requiring a loose
  // tolerance of 30 on the dominant Y axis. Wheel scrolls do not have slop,
  // so we use a small tolerance of 1. For the minor X axis in the touch test,
  // we also use a small tolerance so that locking (scrollLeft=0) is still
  // disallowed.
  const tolerance_x = 1;
  const tolerance_y = (input_source === 'touch') ? 30 : 1;

  const end_x = start_x - delta_x;
  const end_y = start_y - delta_y;

  const scrollend_promise =
      waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller);

  if (input_source === 'touch') {
    await new test_driver.Actions()
      .addPointer("finger", "touch")
      .pointerMove(Math.round(start_x), Math.round(start_y))
      .pointerDown()
      .addTick()
      .pause(100)
      .pointerMove(Math.round(end_x), Math.round(end_y))
      .addTick()
      .pause(100) // Pause to avoid fling
      .pointerUp()
      .send();
  } else if (input_source === 'wheel') {
    scroller.addEventListener('wheel', (e) => {
      received_wheel_event = e;
    }, { once: true });

    await new test_driver.Actions()
      .addWheel("wheel")
      .scroll(0, 0, Math.round(delta_x), Math.round(delta_y),
              {origin: scroller})
      .send();
  }

  // Wait for scroll to end.
  await scrollend_promise;

  assert_approx_equals(scroller.scrollTop, delta_y, tolerance_y,
    "Should have scrolled vertically");
  assert_approx_equals(
      scroller.scrollLeft, delta_x, tolerance_x,
      "Should have scrolled horizontally (not railed to Y)");

  if (input_source === 'wheel') {
    // The wheel delta will always be the unlocked value.
    // With scroll-axis-lock: none, the wheel delta should match the scroll
    // delta.
    assert_not_equals(received_wheel_event, null,
                      "Should have received a wheel event");
    assert_equals(received_wheel_event.deltaX, delta_x,
                  "wheel event deltaX should match sent delta");
    assert_equals(received_wheel_event.deltaY, delta_y,
                  "wheel event deltaY should match sent delta");
  }
}

promise_test(async t => {
  await run_test(t, 'touch');
}, "scroll-axis-lock: none allows free diagonal touch scroll " +
   "even with steep angle (no railing)");

promise_test(async t => {
  await run_test(t, 'wheel');
}, "scroll-axis-lock: none allows free diagonal wheel scroll " +
   "even with steep angle (no railing)");
</script>