Skip to content

Commit

Permalink
❄️ Fix amp-carousel e2e tests to use the slides' bounding rect instea…
Browse files Browse the repository at this point in the history
…d of scrollLeft (#39515)
  • Loading branch information
danielrozenberg authored Oct 4, 2023
1 parent fe977c0 commit b48f04b
Showing 1 changed file with 104 additions and 103 deletions.
207 changes: 104 additions & 103 deletions extensions/amp-base-carousel/0.1/test-e2e/test-carousel.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import {getScrollingElement, getSlide, waitForCarouselImg} from './helpers';
import {
getScrollingElement,
getSlide,
getSlides,
waitForCarouselImg,
} from './helpers';

const pageWidth = 800;
const pageHeight = 600;

/** Increase timeout for running on macOS **/
const testTimeout = 20000;
/** Increased timeout for long-running tests. **/
const testTimeout = 8_000;

describes.endtoend(
'amp-base-carousel - basic functionality',
Expand All @@ -25,94 +30,107 @@ describes.endtoend(
const SLIDE_COUNT = 7;
let controller;

function prop(el, name) {
return controller.getElementProperty(el, name);
}

beforeEach(async function () {
controller = env.controller;
});

it.skip('should render correctly', async function () {
this.timeout(testTimeout);
const el = await getScrollingElement(controller);
it('should render correctly', async function () {
const slides = await getSlides(controller);
const slidesRects = await Promise.all(
slides.map(async (slide) => await controller.getElementRect(slide))
);

// We should have space for SLIDE_COUNT - 1 on either side + 1 for the
// current slide.
await expect(prop(el, 'scrollWidth')).to.equal(
pageWidth * (2 * (SLIDE_COUNT - 1) + 1)
// Slides are placed on both the left and the right of the 0th slide, so
// that scrolling on either direction work for the looping carousel. This
// verifies that all slides are positioned side-by-side with the total
// expected width.
const slidesLeftmost = Math.min(...slidesRects.map(({left}) => left));
const slidesRightmost = Math.max(...slidesRects.map(({right}) => right));
await expect(slidesRightmost - slidesLeftmost).to.equal(
pageWidth * SLIDE_COUNT
);

// Verify that the 0th slide is layed out and is at the start, and that its
// width is equal to the page.
await waitForCarouselImg(controller, 0);
await expect(slidesRects[0].left).to.equal(0);
await expect(slidesRects[0].width).to.equal(pageWidth);
});

it('should layout the two adjacent slides', async function () {
this.timeout(testTimeout);
// TODO(sparhami) Verify this is on the right of the 0th slide
const [firstSlideRect, secondSlideRect, lastSlideRect] = [
await controller.getElementRect(await getSlide(controller, 0)),
await controller.getElementRect(await getSlide(controller, 1)),
await controller.getElementRect(
await getSlide(controller, SLIDE_COUNT - 1)
),
];

// Verify that the second slide is layed out and is to the right of the
// starting slide.
await waitForCarouselImg(controller, 1);
// TODO(sparhami) Verify this is on the left of the 0th slide
await expect(secondSlideRect.left).to.equal(firstSlideRect.right);

// Verify that the last slide is layed out and is to the left of the
// starting slide.
await waitForCarouselImg(controller, SLIDE_COUNT - 1);
await expect(lastSlideRect.right).to.equal(firstSlideRect.left);
});

it('should snap when scrolling', async function () {
this.timeout(testTimeout);
const el = await getScrollingElement(controller);
const firstSlide = await getSlide(controller, 0);
const secondSlide = await getSlide(controller, 1);

// Wait for the first two slides's imgs to load.
await waitForCarouselImg(controller, 0);
await waitForCarouselImg(controller, 1);

const slideWidth = await prop(firstSlide, 'offsetWidth');
const scrollLeft = await prop(el, 'scrollLeft');
const snappedScrollLeft = scrollLeft + slideWidth;
const requestedScrollLeft = snappedScrollLeft + 1;
await expect(controller.getElementRect(secondSlide)).to.contain({
left: pageWidth,
});

await controller.scrollTo(el, {left: requestedScrollLeft});
await controller.scrollBy(el, {left: 1});
// We should have snapped to the edge of the slide rather than the
// requested scroll position.
await expect(prop(el, 'scrollLeft')).to.equal(snappedScrollLeft);
await expect(controller.getElementRect(secondSlide)).to.contain({
left: 0,
});
});

it('should reset the window after scroll', async function () {
this.timeout(testTimeout);
const el = await getScrollingElement(controller);
const firstSlide = await getSlide(controller, 0);
const slides = await getSlides(controller);
const slidesRects = await Promise.all(
slides.map(async (slide) => await controller.getElementRect(slide))
);

// Wait for the first two slides's imgs to load.
await waitForCarouselImg(controller, 0);
await waitForCarouselImg(controller, 1);

const slideWidth = await prop(firstSlide, 'offsetWidth');
const scrollWidth = await prop(el, 'scrollWidth');
const scrollLeft = await prop(el, 'scrollLeft');
const snappedScrollLeft = scrollLeft + slideWidth;
const requestedScrollLeft = snappedScrollLeft + 1;

await controller.scrollTo(el, {left: requestedScrollLeft});
// Wait for the scrolling to settle
await expect(prop(el, 'scrollLeft')).to.equal(snappedScrollLeft);
// The new scroll width/left should eventually be the same as before,
// since the windowing should have been reset around the new element.
await expect(prop(el, 'scrollWidth')).to.equal(scrollWidth);
await expect(prop(el, 'scrollLeft')).to.equal(scrollLeft);
await controller.scrollBy(el, {left: 1});
// See `should render correctly`. Results here should be the same after
// the scroll settles.
const slidesLeftmost = Math.min(...slidesRects.map(({left}) => left));
const slidesRightmost = Math.max(...slidesRects.map(({right}) => right));
await expect(slidesRightmost - slidesLeftmost).to.equal(
pageWidth * SLIDE_COUNT
);
});

// TODO(wg-components, #27701): Flaky on Chrome+viewer environment.
it.skip('should have the correct scroll position when resizing', async function () {
this.timeout(testTimeout);
it('should have the correct scroll position when resizing', async function () {
const firstSlide = await getSlide(controller, 0);
// Note: 513 seems to be the smallest settable width.
await controller.setWindowRect({
width: 800,
height: 600,
});

const firstSlide = await getSlide(controller, 0);

// Wait for the first two slides's imgs to load.
await waitForCarouselImg(controller, 0);
await waitForCarouselImg(controller, 1);
await expect(controller.getElementRect(firstSlide)).to.include({
'x': 0,
'left': 0,
'width': 800,
});

Expand All @@ -123,14 +141,15 @@ describes.endtoend(

// Normally, resizing would cause the position to change. We're testing
// that the carousel moves this to the correct position again.
// TODO(wg-components, #27701): Flaky on Chrome+viewer environment.
// Commented-out the comparison to `'left': 0` until fixed.
await expect(controller.getElementRect(firstSlide)).to.include({
'x': 0,
/* 'left': 0, */
'width': 900,
});
});

it.skip('should go to slide 0 when index is set to 0 ', async function () {
this.timeout(testTimeout);
it('should go to slide 0 when index is set to 0', async function () {
const el = await getScrollingElement(controller);

const firstSlide = await getSlide(controller, 0);
Expand All @@ -142,16 +161,17 @@ describes.endtoend(
await waitForCarouselImg(controller, 0);
await waitForCarouselImg(controller, 1);

await controller.scrollTo(el, {left: 1});
await expect(controller.getElementRect(secondSlide)).to.include({x: 0});
await controller.scrollBy(el, {left: 1});
await expect(controller.getElementRect(secondSlide)).to.include({
left: 0,
});

await controller.click(goToSlideBtn);
await expect(controller.getElementRect(firstSlide)).to.include({x: 0});
await expect(controller.getElementRect(firstSlide)).to.include({left: 0});
});

describe('looping', function () {
it('should show the last slide when looping', async function () {
this.timeout(testTimeout);
const el = await getScrollingElement(controller);
const lastSlide = await getSlide(controller, SLIDE_COUNT - 1);

Expand All @@ -160,91 +180,72 @@ describes.endtoend(
await waitForCarouselImg(controller, SLIDE_COUNT - 1);

// Scroll to the previous slide by moving left by the last slide's width.
const slideWidth = await prop(lastSlide, 'offsetWidth');
const restingScrollLeft = await prop(el, 'scrollLeft');
const snappedScrollLeft = restingScrollLeft - slideWidth;
const requestedScrollLeft = snappedScrollLeft - 1;
await controller.scrollTo(el, {left: requestedScrollLeft});

await expect(prop(el, 'scrollLeft')).to.equal(snappedScrollLeft);
await controller.scrollBy(el, {left: -1});
await expect(controller.getElementRect(lastSlide)).to.include({
left: 0,
});
});

it('should show the first slide when looping', async function () {
this.timeout(testTimeout);
const el = await getScrollingElement(controller);
const firstSlide = await getSlide(controller, 0);
const lastSlide = await getSlide(controller, SLIDE_COUNT - 1);

// Wait for the first and last slides to load.
await waitForCarouselImg(controller, 0);
await waitForCarouselImg(controller, SLIDE_COUNT - 1);

// Go to the last slide, wait for scrolling to move and window to reset.
const slideWidth = await prop(lastSlide, 'offsetWidth');
const restingScrollLeft = await prop(el, 'scrollLeft');
const lastSlideScrollPos = restingScrollLeft - slideWidth;
await controller.scrollTo(el, {left: lastSlideScrollPos});
await expect(prop(el, 'scrollLeft')).to.equal(lastSlideScrollPos);
await expect(prop(el, 'scrollLeft')).to.equal(restingScrollLeft);

// Go to the next slide by moving the slides width to the right.
const snappedScrollLeft = restingScrollLeft + slideWidth;
const requestedScrollLeft = snappedScrollLeft + 1;
await controller.scrollTo(el, {left: requestedScrollLeft});

await expect(prop(el, 'scrollLeft')).to.equal(snappedScrollLeft);
await controller.scrollBy(el, {left: -1});
await expect(controller.getElementRect(lastSlide)).to.include({
left: 0,
});

// Go to the next slide.
await controller.scrollBy(el, {left: 1});
await expect(controller.getElementRect(firstSlide)).to.include({
left: 0,
});
});

// When resting the last few slides should be translated to the left.
// Make sure we can move all the way forwards to the last slide and that it
// is in the right place.
it('should display slides correctly when moving forwards', async function () {
// TODO(wg-components, #27701): Flaky on Chrome+viewer environment.
it.skip('should display slides correctly when moving forwards', async function () {
this.timeout(testTimeout);
const el = await getScrollingElement(controller);
const lastSlide = await getSlide(controller, SLIDE_COUNT - 1);
const slides = await getSlides(controller);

// Wait for the first and last slides to load.
await waitForCarouselImg(controller, 0);
await waitForCarouselImg(controller, SLIDE_COUNT - 1);

// Go to the last slide, wait for scrolling to move.
const slideWidth = await prop(lastSlide, 'offsetWidth');
const restingScrollLeft = await prop(el, 'scrollLeft');
await controller.scrollTo(el, {
left: slideWidth * (SLIDE_COUNT - 2),
});

await expect(prop(el, 'scrollLeft')).to.equal(restingScrollLeft);
await expect(controller.getElementRect(lastSlide)).to.include({
x: 0,
width: slideWidth,
});
// Loop through all the slides, wait for each of them to land in place.
for (const slide of slides) {
await controller.scrollBy(el, {left: 1});
await expect(controller.getElementRect(slide)).to.include({left: 0});
}
});

// When resting the first few slides should be translated to the right.
// Make sure we can move all the way backwards to the second slide and that
// it is in the right place.
it('should display slides correctly when moving backwards', async function () {
// TODO(wg-components, #27701): Flaky on Chrome+viewer environment.
it.skip('should display slides correctly when moving backwards', async function () {
this.timeout(testTimeout);
const el = await getScrollingElement(controller);
const secondSlide = await getSlide(controller, 1);
const slides = await getSlides(controller);

// Wait for the first and second slides to load.
await waitForCarouselImg(controller, 0);
await waitForCarouselImg(controller, 1);

// Go to the last slide, wait for scrolling to move.
const slideWidth = await prop(secondSlide, 'offsetWidth');
const restingScrollLeft = await prop(el, 'scrollLeft');
await controller.scrollTo(el, {
left: -(slideWidth * (SLIDE_COUNT - 2)),
});

await expect(prop(el, 'scrollLeft')).to.not.equal(restingScrollLeft);
await expect(prop(el, 'scrollLeft')).to.equal(restingScrollLeft);
await expect(controller.getElementRect(secondSlide)).to.include({
x: 0,
width: slideWidth,
});
// Loop through all the in reverse, wait for each of them to land in place.
for (const slide of [...slides].reverse()) {
await controller.scrollBy(el, {left: -1});
await expect(controller.getElementRect(slide)).to.include({left: 0});
}
});
});
}
Expand Down

0 comments on commit b48f04b

Please sign in to comment.